使用字典列向 pandas 数据框添加行

问题描述 投票:0回答:5

我有一个像这样的数据框:

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 

任何帮助将不胜感激:)

pandas dictionary
5个回答
2
投票

始终尝试构建数据,可以轻松完成,如下所示:

>>> 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

0
投票

使用

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

0
投票

您可以通过解压字典,同时使用

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

0
投票

使用

df1
作为值,使用
df['dict_of item_counts'].tolist()
作为索引构建数据框
df.ordernum
replace
0 与
np.nan
stack
与 dropna=True 忽略 0 值。
reset_index
获取所有列。

接下来,使用

ordernum_index
groupby
创建列
cumcount

最后,将列名更改为合适的名称。

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

0
投票
dd1=df1.set_index("ordernum").dict_of2item_counts.map(eval).apply(pd.Series).stack().reset_index().rename(columns={'level_1':"key",0:"value"}).query("value>0")
dd1.assign(ordernum_index=dd1.groupby("ordernum").key.transform('rank',method='first').astype(int))


  ordernum key  value  ordernum_index
0       222   a      1               1
1       222   b      3               2
2       222   c      2               3
3       222   d      1               4
4       333   a      1               1
7       333   d      1               2
© www.soinside.com 2019 - 2024. All rights reserved.