在Pandas中从字典中提取信息
我有一个DataFrame:
import pandas as pd
d1 = str([{"Alice": "1/2"}, {"Bob": "3/11"}, {"Charlotte": "5/2"}])
d2 = str([{"Bob": "2/7"}, {"Daniel": "4/5"}])
d3 = str([{"Emily": "12/5"}])
d4 = str([{"Bob": "4/11"}, {"Victor": "2/2"}, {"Bob": "5/6"}])
df = pd.DataFrame([d1, d2, d3, d4], columns=['visits'])
我把每一行看作诊所里一个房间的对应项,每个字典包含在那个房间中的病人以及他们在场的日期。我想为每位病人创建一个新列,用来统计该病人出现在每个房间的次数(该列中的字典中,有多少个键等于该病人的名字):
df_desired = pd.DataFrame(
[[d1, 1, 1, 1, 0, 0, 0],
[d2, 0, 1, 0, 1, 0, 0],
[d3, 0, 0, 0, 0, 1, 0],
[d4, 0, 2, 0, 0, 0, 1]],
columns=['visits', 'Alice', 'Bob', 'Charlotte', 'Daniel', 'Emily', 'Victor'])
如何实现?我不知道所有病人是谁(字典中的键都会有哪些)。逐行遍历不是正确的答案,因为性能真的很差。
解决方案
First you have to convert it back from strings to list of dictionaries
import ast
data = df["visits"].apply(ast.literal_eval)
Next you get all names in rows:
names = data.apply(lambda lst: [list(item.keys())[0] for item in lst])
0 [Alice, Bob, Charlotte]
1 [Bob, Daniel]
2 [Emily]
3 [Bob, Victor, Bob]
Next you convert it to one column using explode
all_names = names.explode()
0 Alice
0 Bob
0 Charlotte
1 Bob
1 Daniel
2 Emily
3 Bob
3 Victor
3 Bob
And next you can use crosstab to get expected values.
(I was thinking also about get_dummies() but it would need to groupby() and sum())
table = pd.crosstab(all_names.index, all_names.values)
col_0 Alice Bob Charlotte Daniel Emily Victor
row_0
0 1 1 1 0 0 0
1 0 1 0 1 0 0
2 0 0 0 0 1 0
3 0 2 0 0 0 1
And finally you may join it with original DataFrame
df = df.join(table)
visits Alice Bob Charlotte Daniel Emily Victor
0 [{'Alice': '1/2'}, {'Bob': '3/11'}, {'Charlott... 1 1 1 0 0 0
1 [{'Bob': '2/7'}, {'Daniel': '4/5'}] 0 1 0 1 0 0
2 [{'Emily': '12/5'}] 0 0 0 0 1 0
3 [{'Bob': '4/11'}, {'Victor': '2/2'}, {'Bob': '... 0 2 0 0 0 1
Full working code with example data directly in code - so everyone can simply copy and test it.
import pandas as pd
import ast
d1 = str([{"Alice": "1/2"}, {"Bob": "3/11"}, {"Charlotte": "5/2"}])
d2 = str([{"Bob": "2/7"}, {"Daniel": "4/5"}])
d3 = str([{"Emily": "12/5"}])
d4 = str([{"Bob": "4/11"}, {"Victor": "2/2"}, {"Bob": "5/6"}])
df = pd.DataFrame([d1, d2, d3, d4], columns=["visits"])
# ----
# convert it back from string to list of dictionares
data = df["visits"].apply(ast.literal_eval)
# print(df)
names = data.apply(lambda lst: [list(item.keys())[0] for item in lst])
#print(names)
all_names = names.explode()
#print(all_names)
table = pd.crosstab(all_names.index, all_names.values)
#table = pd.get_dummies(all_names).groupby(level=0).sum()
#print(table)
df = df.join(table)
print(df)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。