如何映射到 pandas 中列表列内的值
How to map to values inside a column of lists in pandas
我有以下场景。
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。
试试这个:
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)
- 对于具有 1M 行的示例数据帧,具有
list-comprehension
的 .apply
比具有 .groupby()
的 .explode()
快约 2.5 倍,并且快一点(1.15 倍) 而不是使用 .map()
。
- 见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)
df.col2.map(lambda x: list(map(my_dict.get, x)))
我有以下场景。
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。
试试这个:
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)
- 对于具有 1M 行的示例数据帧,具有
list-comprehension
的.apply
比具有.groupby()
的.explode()
快约 2.5 倍,并且快一点(1.15 倍) 而不是使用.map()
。- 见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)
df.col2.map(lambda x: list(map(my_dict.get, x)))