パンダ:長い形式のデータフレームに値がないにもかかわらず、すべての行にすべての列を含めるにはどうすればよいですか?
これは最初は奇妙な質問のように聞こえるかもしれませんが、のデータの要素について話すときに「標準的な」用語を見つけるのは難しいと思いましたlong format
。だから私は、ハドリー・ウィッカムがTidyDataに関する彼の記事の最初の例の1つで使用しているのと同じ用語を使用したいと思いました。

私の実際のデータのサンプルでは、行には日付が含まれ、列にはカテゴリが含まれ、値には次のような価格が含まれています。
入力
row column value
0 21.08.2020 A 43
1 21.08.2020 A 36
2 21.08.2020 B 36
3 21.08.2020 C 28
4 22.08.2020 A 16
5 22.08.2020 B 40
6 22.08.2020 B 34
ここでは、column
値は上の画像ほど規則的ではありません。一部の行値で一部の列値が欠落しています。値をに設定して同じデータセットにこれらの列名を含めるにはどうすればよい0
ですか?上記のサンプルデータフレームでは、次の場合にcolumn C
のみ発生しrow = 21.08.2020
ます。
これを考慮して含めることができるパンダ関数はあります22.08.2020 C 0
か?
必要な出力
row column value
0 21.08.2020 A 43
1 21.08.2020 A 36
2 21.08.2020 B 36
3 21.08.2020 C 28
4 22.08.2020 A 16
5 22.08.2020 B 40
6 22.08.2020 B 34
7 22.08.2020 C 0
すべてを取得しunique column values = ['A', 'B', 'C']
、すべての行の値をループしてvalue = 0
、欠落している列を挿入するアプローチを試しましたが、それは非常に高速になりました。だから他の提案は素晴らしいでしょう!
編集:pd.pivotを使用して長いものから広いものへ
を使用pd.pivot_table(df1,index='row',columns='column',values='value')
すると、上記の入力データフレームが次のようになります。
column A B C
row
21.08.2020 39.5 36.0 28.0
22.08.2020 16.0 37.0 NaN
ここでは、NaN
デフォルトで含まれているcolumn=C
とrow=22.08.2020
。したがって、このデータフレームを削除せずに目的の出力にメルトまたはピボットする場合が残りNaN
ます。
編集2:サンプルデータフレーム
import pandas as pd
df=pd.DataFrame({'row': {0: '21.08.2020',
1: '21.08.2020',
2: '21.08.2020',
3: '21.08.2020',
4: '22.08.2020',
5: '22.08.2020',
6: '22.08.2020'},
'column': {0: 'A', 1: 'A', 2: 'B', 3: 'C', 4: 'A', 5: 'B', 6: 'B'},
'value': {0: 43, 1: 36, 2: 36, 3: 28, 4: 16, 5: 40, 6: 34}})
回答
同じ行に複数の値があるため、これは前のものとは異なります
df['key']=df.groupby(['row','column']).cumcount()
df1 = pd.pivot_table(df,index='row',columns=['key','column'],values='value')
df1 = df1.stack(level=[0,1],dropna=False).to_frame('value').reset_index()
df1 = df1[df1.key.eq(0) | df1['value'].notna()]
df1
Out[97]:
row key column value
0 21.08.2020 0 A 43.0
1 21.08.2020 0 B 36.0
2 21.08.2020 0 C 28.0
3 21.08.2020 1 A 36.0
6 22.08.2020 0 A 16.0
7 22.08.2020 0 B 40.0
8 22.08.2020 0 C NaN
10 22.08.2020 1 B 34.0
私pd.pivot()
はと組み合わせてアプローチを見つけましたunstack()
:
import pandas as pd
df=pd.DataFrame({'row': {0: '21.08.2020',
1: '21.08.2020',
2: '21.08.2020',
3: '21.08.2020',
4: '22.08.2020',
5: '22.08.2020',
6: '22.08.2020'},
'column': {0: 'A', 1: 'A', 2: 'B', 3: 'C', 4: 'A', 5: 'B', 6: 'B'},
'value': {0: 43, 1: 36, 2: 36, 3: 28, 4: 16, 5: 40, 6: 34}})
df1 = pd.pivot_table(df,index='row',columns='column',values='value').unstack().reset_index()
print(df1)
出力
column row 0
0 A 21.08.2020 39.5
1 A 22.08.2020 16.0
2 B 21.08.2020 36.0
3 B 22.08.2020 37.0
4 C 21.08.2020 28.0
5 C 22.08.2020 NaN
ただし、データフレーム列の順序は間違いなく混乱しています...
これは単純なアプローチです-forループを使用します。
data = {'row': {0: '21.08.2020', 1: '21.08.2020', 2: '21.08.2020',
3: '21.08.2020', 4: '22.08.2020', 5: '22.08.2020',
6: '22.08.2020'},
'column': {0: 'A', 1: 'A', 2: 'B', 3: 'C', 4: 'A', 5: 'B', 6: 'B'},
'value': {0: 43, 1: 36, 2: 36, 3: 28, 4: 16, 5: 40, 6: 34}}
df = pd.DataFrame(data)
categories = set(df.column.unique())
tbl = pd.pivot_table(df[['row','column']],values='column',index='row',aggfunc=set)
missing = tbl.column.apply(categories.difference)
missing = filter(lambda x:x[1],missing.items())
d = collections.defaultdict(list)
#d = {'row':[],'column':[],'value':[]}
for row,col in missing:
for cat in col:
d['row'].append(row)
d['column'].append(cat)
d['value'].append(0)
df2 = df.append(pd.DataFrame(d))。reset_index()
df2 = df.append(pd.DataFrame(d)).reset_index()
もちろん、すべての新しい値は最後になり、それが問題になる場合は並べ替える必要があります。
中間オブジェクト:
>>> tbl
column
row
21.08.2020 {A, B, C}
22.08.2020 {A, B}
>>> missing
row
21.08.2020 {}
22.08.2020 {C}
Name: column, dtype: object
>>>
ここでalternative.itが設定されrow
且つcolumn
、新たなインデックスとして列をの値のすべての可能な組み合わせを取得row
し、column
列、及びジョイン(方法=「外側」)を持つ空のデータフレームrow
とcolumn
新しい指標としての組合せ:
From itertools import product
new_index = product(set(df.row.array), set(df.column.array))
df = df.set_index(["row", "column"])
new_index = pd.DataFrame([], index=pd.Index(new_index, names=["row", "column"]))
df.join(new_index, how="outer").reset_index().astype({"value": "Int8"}) # if you are keen on nullable integers
row column value
0 21.08.2020 A 43
1 21.08.2020 A 36
2 21.08.2020 B 36
3 21.08.2020 C 28
4 22.08.2020 A 16
5 22.08.2020 B 40
6 22.08.2020 B 34
7 22.08.2020 C <NA>