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

时间:2021-01-29 21:36:17

标签: python pandas dictionary lambda data-science

我有以下场景。

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]))

我真的被困住了,想知道是否可以不编写单独的函数,然后将其作为参数传递给 apply。

3 个答案:

答案 0 :(得分:5)

  • 对于具有 100 万行的示例数据帧,带有 .applylist-comprehension 比带有 .explode().groupby() 快大约 2.5 倍,并且比 .map() 快一点(1.15 倍)使用 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) 测试

{{1}}

答案 1 :(得分:3)

试试这个:

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)

答案 2 :(得分:0)

df.col2.map(lambda x: list(map(my_dict.get, x)))