在Pandas中从字典中提取信息

后端开发 2026-07-10

我有一个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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章