复杂的列表列到列字符串匹配和派生另一列

complicated list column to column string matching and deriving another column

数据帧:

df1:
ind_lst
[agriculture_dairy, analytics]
[architecture_planning, advertising_pr_events, analytics]

df2:
ind    score
advertising_pr_events   3.672947168
agriculture_dairy   3.368266582
airlines_aviation_aerospace 3.60798955
analytics   3.67752552
architecture_planning   3.853236675

我有2个数据框,如上所示。

df2 的 ind 列是字符串类型并且具有行业名称。 df2.score 每个行业都有一个独特的分数。

df1的ind_lst列是df2.ind

的独特元素的不同组合形成的行业名称列表

我想在 df1 avg_score 中创建一个列,最终输出如下:

avg_score 在 df1 的第 1 行是来自 df2 的分数的平均值对应于 agriculture_dairy,analytics

df1 的第 2 行中的

avg_score 是来自 df2 的分数的平均值,对应于 architecture_planning、advertising_pr_events、分析。

df1
ind_lst    avg_score
[agriculture_dairy, analytics]    3.522896051
[architecture_planning, advertising_pr_events, analytics]    3.734569787666667

如何在python中实现这个? 我试过这个:

avg=[]
avgs=[]
for i in df1.ind_lst:
    for j in i:
        a= df2[df2['ind'] == j].index
        avg.append(df2.loc[a]['score'])
    avgs.append(mean(avg))
    

df1['avg_score']= avgs

代码运行不正常。我得到一个空列表作为输出。

注意:我已经对数据帧进行了采样并仅共享了问题陈述的一部分。真实的数据帧 df1 有 90k 个条目 & df2 有 860 行。

选项 1:根据 df2 创建 ind 和 score 地图。使用列表理解将分数映射到行业并计算平均值。

mapper = df2.set_index('ind')['score'].to_dict()
df1['avg_score'] = df1['ind_lst'].apply(lambda x: np.mean([mapper[i] for i in x]))

    ind_lst                                             avg_score
0   [agriculture_dairy, analytics]                      3.522896
1   [architecture_planning, advertising_pr_events,...   3.734570

选项 2:使用 DataFrame.explode 取消嵌套列表,groupby 索引并应用 mean

df1['avg_score'] = df1['ind_lst'].explode().map(mapper).groupby(level = 0).mean()

您可以像这样使用列表作为 df2 的索引,而不是像 那样使用映射器和列表理解。

df1["average_score"] = df1["ind_lst"].apply(lambda lst: df2.loc[lst, "score"].mean())