如何映射到熊猫列表列中的值

Posted

技术标签:

【中文标题】如何映射到熊猫列表列中的值【英文标题】:How to map to values inside a column of lists in pandas 【发布时间】:2021-05-03 19:41:59 【问题描述】:

我有以下场景。

import pandas as pd

d = 'col1': [1, 2, 3], 'col2': [['apple'], [], ['romaine', 'potatoes']
df = pd.DataFrame(data=d)

所以数据框是:

   col1   col2
0   1     [apple]
1   2     []
2   3     [romaine, potatoes]

我还有一本字典:

my_dict = "apple" : "fruit", "potatoes" : "vegetable", "romaine" : "lettuce"

我想创建另一列“col3”,其中包含来自上面 my_dict 的值列表:

   col1   col2                 col3
0   1     [apple]              [fruit]
1   2     []                   []
2   3     [romaine, potatoes]  [lettuce, vegetable]

我想用apply、map、lambda写一行代码来实现:

df["col3"] = df.col2.apply(map(lambda x: pass if not x else condition_dict[x]))

我真的很困惑,想知道是否可以不编写单独的函数然后作为参数传递给应用。

【问题讨论】:

【参考方案1】: 对于具有 1M 行的示例数据帧,.applylist-comprehension.explode().groupby() 快大约 2.5 倍,并且比使用 .map() 快一点(1.15 倍)。 见List comprehension vs map 如果列中有NaN,则该行必须用.dropna 删除,也可以用空的list 填充。 .fillna([]) 不起作用 使用df.col2 = df.col2.fillna(i: [] for i in df.index)
df['col3'] = df.col2.apply(lambda x: [my_dict.get(v) for v in x])

# display(df)
 col1                col2                 col3
    1             [apple]              [fruit]
    2                  []                   []
    3 [romaine, potatoes] [lettuce, vegetable]

%timeit测试

# test data with 1M rows
d = 'col1': [1, 2, 3], 'col2': [['apple'], [], ['romaine', 'potatoes']]
df = pd.DataFrame(d)
df = pd.concat([df]*333333)

%%timeit
df.col2.apply(lambda x: [my_dict.get(v) for v in x])
[out]:
453 ms ± 30.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

def scott(d, my_dict):
    e = d.explode('col2')
    e['col3'] = e['col2'].map(my_dict)
    return e.groupby('col1', as_index=False)[['col3']].agg(list).merge(d)

%%timeit
scott(df, my_dict)
[out]:
1.17 s ± 23.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
df.col2.map(lambda x: list(map(my_dict.get, x)))
[out]:
519 ms ± 16.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
df['col2'].explode().map(my_dict).groupby(level=0).agg(list)
[out]:
909 ms ± 8.61 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

【参考方案2】:

试试这个:

dfe = df.explode('col2')
dfe['col3'] = dfe['col2'].map(my_dict)
dfe.groupby('col1', as_index=False)[['col3']].agg(list).merge(df)

输出:

   col1                  col3                 col2
0     1               [fruit]              [apple]
1     2                 [nan]                   []
2     3  [lettuce, vegetable]  [romaine, potatoes]

或者作为单行:

(df.merge(df['col2'].explode()
                    .map(my_dict)
                    .groupby(df['col1'])
                    .agg(list)
                    .rename('col3'), 
           left_on='col1', 
           right_index=True)

【讨论】:

【参考方案3】:
df.col2.map(lambda x: list(map(my_dict.get, x)))

【讨论】:

以上是关于如何映射到熊猫列表列中的值的主要内容,如果未能解决你的问题,请参考以下文章

熊猫,根据行中的值创建列

从列表列表中提取元素并将其分配为熊猫数据框列中的值

如何比较字典值中的多个数组,并将每个数组元素的字典键映射到新数组/列表中

如何使用熊猫对与给定条件匹配的列中的值求和?

我想在列中的值中添加“%”单位

如何获取熊猫数据框中的行,列中具有最大值并保留原始索引?