>我有一个这样的数据帧:
matrix = [(222, {'a': 1, 'b':3, 'c':2, 'd':1}),
(333, {'a': 1, 'b':0, 'c':0, 'd':1})]
df = pd.DataFrame(matrix, columns=['ordernum', 'dict_of item_counts'])
ordernum dict_of item_counts
0 222 {'a': 1, 'b': 3, 'c': 2, 'd': 1}
1 333 {'a': 1, 'b': 0, 'c': 0, 'd': 1}
我想创建一个数据帧,其中每个ordernum
对每个字典键重复dict_of_item_counts
不是 0。我还想创建一个显示此行的相应字典键的key
列以及一个包含字典值的value
列。最后,我还会ordernum_index
,用于计算每个ordernum
的数据帧中的不同行。
最终数据帧应如下所示:
ordernum ordernum_index key value
222 1 a 1
222 2 b 3
222 3 c 2
222 4 d 1
333 1 a 1
333 2 d 1
任何帮助将不胜感激:)
始终尝试构建数据,可以轻松完成,如下所示:
>>> matrix
[(222, {'a': 1, 'b': 3, 'c': 2, 'd': 1}), (333, {'a': 1, 'b': 0, 'c': 0, 'd': 1})]
>>> data = [[item[0]]+[i+1]+list(value) for item in matrix for i,value in enumerate(item[1].items()) if value[-1]!=0]
>>> data
[[222, 1, 'a', 1], [222, 2, 'b', 3], [222, 3, 'c', 2], [222, 4, 'd', 1], [333, 1, 'a', 1], [333, 4, 'd', 1]]
>>> pd.DataFrame(data, columns=['ordernum', 'ordernum_index', 'key', 'value'])
ordernum ordernum_index key value
0 222 1 a 1
1 222 2 b 3
2 222 3 c 2
3 222 4 d 1
4 333 1 a 1
5 333 4 d 1
通过将apply
与pd.Series
一起使用来扩展字典,并使用concat
将其连接到其他列(ordernum(。请参阅下面的中间结果 df2
。现在要将每一列变成一行,请使用 melt
,然后使用 query
删除所有 0 行,最后assign
cumcount
以获取索引(排序后(并添加 1 从 1 开始计数,而不是 0。
df2 = pd.concat([df[['ordernum']], df['dict_of item_counts'].apply(pd.Series)], axis=1)
(df2.melt(id_vars='ordernum', var_name='key')
.query('value != 0')
.sort_values(['ordernum', 'key'])
.assign(ordernum_index = lambda df: df.groupby('ordernum').cumcount().add(1)))
# ordernum key value ordernum_index
#0 222 a 1 1
#2 222 b 3 2
#4 222 c 2 3
#6 222 d 1 4
#1 333 a 1 1
#7 333 d 1 2
现在 df2 看起来像:
# ordernum a b c d
#0 222 1 3 2 1
#1 333 1 0 0 1
解压缩字典来做到这一点,同时使用 iterrows
访问字典并从ordernum, key, value
中创建元组。
最后,为了创建您的ordernum_index
我们在ordernum
上分组并执行cumcount
:
data = [(r['ordernum'], k, v) for _, r in df.iterrows() for k, v in r['dict_of item_counts'].items() ]
new = pd.DataFrame(data, columns=['ordernum', 'key', 'value']).sort_values('ordernum').reset_index(drop=True)
new['ordernum_index'] = new[new['value'].ne(0)].groupby('ordernum').cumcount().add(1)
new.dropna(inplace=True)
ordernum key value ordernum_index
0 222 a 1 1.0
1 222 b 3 2.0
2 222 c 2 3.0
3 222 d 1 4.0
4 333 a 1 1.0
7 333 d 1 2.0
构造数据帧df1
,使用 df['dict_of item_counts'].tolist()
表示值,使用 df.ordernum
表示索引。 replace
0 表示 np.nan
,stack
表示 dropna=True 可忽略 0 值。 reset_index
获取所有列。
接下来,使用 groupby
和 cumcount
创建列ordernum_index
。
最后,将列名称更改为适当的名称。
df1 = pd.DataFrame(df['dict_of item_counts'].tolist(), index=df.ordernum).replace(0, np.nan).stack(dropna=True).reset_index(name='value')
df1['ordernum_index'] = df1.groupby('ordernum')['value'].cumcount() + 1
df1 = df1.rename(columns={'level_1': 'key'})
Out[732]:
ordernum key value ordernum_index
0 222 a 1.0 1
1 222 b 3.0 2
2 222 c 2.0 3
3 222 d 1.0 4
4 333 a 1.0 1
5 333 d 1.0 2