Python 在包含对象列表的列中,根据键名拆分此列,并将值存储为逗号分隔的值
我有一个数据框,其中包含列:Python 在包含对象列表的列中,根据键名拆分此列,并将值存储为逗号分隔的值,python,json,list,pandas,dataframe,Python,Json,List,Pandas,Dataframe,我有一个数据框,其中包含列: A [{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}] [{"A": 31, "B": "hij"},{"A": 32, "B": "abc"}] [{"A": 28, "B": "abc"}] [{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}] [{"A": 28, "B": "abc"},{"A"
A
[{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}]
[{"A": 31, "B": "hij"},{"A": 32, "B": "abc"}]
[{"A": 28, "B": "abc"}]
[{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}]
[{"A": 28, "B": "abc"},{"A": 29, "B": "klm"},{"A": 30, "B": "nop"}]
[{"A": 28, "B": "abc"},{"A": 29, "B": "xyz"}]
输出应确保:
A B
28,29,30 abc,def,hij
31,32 hij,abc
28 abc
28,29,30 abc,def,hij
28,29,30 abc,klm,nop
28,29 abc,xyz
如何根据键名将对象列表拆分为列,并将它们存储为逗号分隔的值,如上图所示。使用
stack
然后groupby
df.A.apply(pd.Series).stack().\
apply(pd.Series).groupby(level=0).\
agg(lambda x :','.join(x.astype(str)))
Out[457]:
A B
0 28,29,30 abc,def,hij
1 31,32 hij,abc
2 28 abc
3 28,29,30 abc,def,hij
4 28,29,30 abc,klm,nop
数据输入:
df=pd.DataFrame({'A':[[{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}],
[{"A": 31, "B": "hij"},{"A": 32, "B": "abc"}],
[{"A": 28, "B": "abc"}],[{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}],
[{"A": 28, "B": "abc"},{"A": 29, "B": "klm"},{"A": 30, "B": "nop"}]]})
有关您的其他问题,请阅读csv
import ast
df=pd.read_csv(r'your.csv',dtype={'A':object})
df['A'] = df['A'].apply(ast.literal_eval)
我假设
A
是一个目录列表
A = [
[{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}],
[{"A": 31, "B": "hij"},{"A": 32, "B": "abc"}],
[{"A": 28, "B": "abc"}],
[{"A": 28, "B": "abc"},{"A": 29, "B": "def"},{"A": 30, "B": "hij"}],
[{"A": 28, "B": "abc"},{"A": 29, "B": "klm"},{"A": 30, "B": "nop"}],
[{"A": 28, "B": "abc"},{"A": 29, "B": "xyz"}]
]
我要做的第一件事是使用理解来创建一本新词典。然后是,。在groupby中加入
B = {
(i, j, k): v
for j, row in enumerate(A)
for i, d in enumerate(row)
for k, v in d.items()
}
pd.Series(B).astype(str).groupby(level=[1, 2]).apply(','.join).unstack()
A B
0 28,29,30 abc,def,hij
1 31,32 hij,abc
2 28 abc
3 28,29,30 abc,def,hij
4 28,29,30 abc,klm,nop
5 28,29 abc,xyz
我想我会试试这个。首先,不要在可以避免的地方使用eval
。更好的解决方案是使用ast
:
import ast
df.A = df.A.apply(ast.literal_eval)
接下来,展平列:
i = df.A.str.len().cumsum() # we'll need this later
df = pd.DataFrame.from_dict(np.concatenate(df.A).tolist())
df.A = df.A.astype(str)
df
A B
0 28 abc
1 29 def
2 30 hij
3 31 hij
4 32 abc
5 28 abc
6 28 abc
7 29 def
8 30 hij
9 28 abc
10 29 klm
11 30 nop
12 28 abc
13 29 xyz
现在,使用i
中的间隔执行groupby
idx = pd.cut(df.index, bins=np.append([0], i), include_lowest=True, right=False)
df = df.groupby(idx, as_index=False).agg(','.join)
df
A B
0 28,29,30 abc,def,hij
1 31,32 hij,abc
2 28 abc
3 28,29,30 abc,def,hij
4 28,29,30 abc,klm,nop
5 28,29 abc,xyz
得到了巴拉斯的一点帮助
IntervalIndex
()的一个很酷的替代方法是使用np.put
:
i = df.A.str.len().cumsum()
df = pd.DataFrame.from_dict(np.concatenate(df.A).tolist())
df.A = df.A.astype(str)
v = pd.Series(0, index=df.index)
np.put(v, i-1, [1] * len(i))
df = df.groupby(v[::-1].cumsum()).agg(','.join)[::-1].reset_index(drop=True)
df
A B
0 28,29,30 abc,def,hij
1 31,32 hij,abc
2 28 abc
3 28,29,30 abc,def,hij
4 28,29,30 abc,klm,nop
5 28,29 abc,xyz
表演
我更喜欢你的,而不是我想出的(-):我会想出一些办法在应用此代码之前,原始列的类型应该是什么?@NikitaGupta dict列表已从csv导入此数据,如何将此列的类型转换为dict列表?@Wen,我已从csv导入此数据,如何将此列的类型转换为dict列表?现在我看到这里+1@Bharath谢谢你的夸奖。我不确定pd.cut是否是最有效的方法,但它是最先出现的。很好!!:-)另外,我在你的问题中添加了一个np.put方法,你能测试一下时间吗?@Wen当然,当我在我的电脑上时会这样做,并让你知道。添加了一个你可能感兴趣的答案(带时间).祝贺10万!!:-)
df = pd.concat([df] * 1000, ignore_index=True)
%%timeit
df.A.apply(pd.Series).stack().\
apply(pd.Series).groupby(level=0).\
agg(lambda x :','.join(x.astype(str)))
1 loop, best of 3: 8.76 s per loop
%%timeit
A = df.A.values.tolist()
B = {
(i, j, k): v
for j, row in enumerate(A)
for i, d in enumerate(row)
for k, v in d.items()
}
pd.Series(B).astype(str).groupby(level=[1, 2]).apply(','.join).unstack()
1 loop, best of 3: 2.08 s per loop
%%timeit
i = df.A.str.len().cumsum()
df2 = pd.DataFrame.from_dict(np.concatenate(df.A).tolist())
df2.A = df2.A.astype(str)
idx = pd.cut(df2.index, bins=np.append([0], i), include_lowest=True, right=False)
df2.groupby(idx, as_index=False).agg(','.join)
1 loop, best of 3: 810 ms per loop
%%timeit
i = df.A.str.len().cumsum()
df2 = pd.DataFrame.from_dict(np.concatenate(df.A).tolist())
df2.A = df2.A.astype(str)
v = pd.Series(0, index=df2.index)
np.put(v, i-1, [1] * len(i))
df2.groupby(v[::-1].cumsum()).agg(','.join)[::-1].reset_index(drop=True)
1 loop, best of 3: 548 ms per loop