我当前的DataFrame是这样的:
Index Animal AnimalClassId
0 [{animalid:1,color:red,name:cat},{animalid:2,color:blue,name:cat2}] 1
1 [{animalid:3,color:pink,name:pig}] 2
所以第一列动物是每一行的字典列表。每个动物行都有一个长度不一的列表。
我的理想输出是:
Index Animal AnimalClassId
0 {animalid:1,color:red,name:cat} 1
1 {animalid:2,color:blue,name:cat2} 1
2 {animalid:3,color:pink,name:pig} 2
此数据集也非常大(超过100000行),因此我试图避免循环遍历每一行。有什么好的方法可以快速实施吗?任何建议,我将不胜感激!
答案 0 :(得分:0)
您可以执行以下操作:
ideal_df = df.set_index(["AnimalClassId"])["Animal"]\
.apply(pd.Series)\
.stack()\
.reset_index(level=1, drop=True)\
.reset_index()
ideal_df.columns = ["AnimalClassId", "Animal"]
(请注意,您可以将其全部放在一行中,也可以分成几行)
示例:
输入(您的示例):
df = pd.DataFrame({
"Animal": [
[{"animalid":1,"color":"red","name":"cat"}, {"animalid":2,"color":"blue","name":"cat2"}],
[{"animalid":3,"color":"pink","name":"pig"}]
],
"AnimalClassId": [1, 2]
})
print(df)
Animal AnimalClassId
0 [{'animalid': 1, 'color': 'red', 'name': 'cat'... 1
1 [{'animalid': 3, 'color': 'pink', 'name': 'pig'}] 2
输出:
print(ideal_df)
AnimalClassId Animal
0 1 {'animalid': 1, 'color': 'red', 'name': 'cat'}
1 1 {'animalid': 2, 'color': 'blue', 'name': 'cat2'}
2 2 {'animalid': 3, 'color': 'pink', 'name': 'pig'}
如果除了“ AnimalClassId”之外,还有更多的列,则需要在传递给set_index
的列表中包括这些列,并将传递给level
的{{1}}参数增加1每增加一列。例如,如果您有“动物栖息地”列,则需要reset_index
和set_index(["AnimalClassId", "AnimalHabitat"])
。
这仍然需要在后台遍历您的数据。由于“动物”列中的数据不是统一的(列表的长度是可变的),我怀疑是否存在一种以矢量化方式扩展每个元素的方法,但这可以解决问题。
答案 1 :(得分:0)
您必须对其进行重建。仔细构建每一列很重要。 一种简单的方法:
def refactor(df):
animals=[]
for list in df.Animal : animals.extend(list) # for O(n) operation
animalclassids=[ id for nb,id in zip(df.Animal.apply(len),df.AnimalClassId)\
for k in range(nb)]
df2= pd.DataFrame({'Animal':animals, 'AnimalClassId':animalclassids})
return df2
col 1的循环避免出现df.Animal.sum()
,这似乎是O(n²)。
>>> refactor(df)
Animal AnimalClassId
0 {'animalid': 1, 'color': 'red', 'name': 'cat'} 1
1 {'animalid': 2, 'color': 'blue', 'name': 'cat2'} 1
2 {'animalid': 3, 'color': 'pink', 'name': 'pig'} 2
>>> df2=pd.concat((df,)*50000)
>>> len(df2)
100000
>>> %time res=refactor(df2)
Wall time: 550 ms
答案 2 :(得分:0)
Pandas代表“面板数据”,当每个系列代表不同的字段时效果最好。因此,您可以扩展数据框,然后取消嵌套字典:
# expand dataframe
df = pd.DataFrame({'Animal': np.concatenate(df['Animal']),
'AnimalClassId': np.repeat(df['AnimalClassId'],
df['Animal'].str.len())})
# un-nested dictionaries into series
df = df.join(pd.DataFrame(df.pop('Animal').values.tolist()))
print(df)
AnimalClassId animalid color name
0 1 1 red cat
0 1 1 red cat
1 2 2 blue cat2
此方法的优势在于,所得数据帧index
保留每行原始数据帧的索引。