假设我有一个数据框,例如:
col1 col2
0 1 A
1 2 B
2 6 A
3 5 C
4 9 C
5 3 A
6 5 B
以及多个列表,例如:
list_1 = [1, 2, 4]
list_2 = [3, 8]
list_3 = [5, 6, 7, 9]
我可以根据列表中是否包含col2
的值来更新col1
的值,例如:
for i in list_1:
df.loc[df.col1 == i, 'col2'] = 'A'
for i in list_2:
df.loc[df.col1 == i, 'col2'] = 'B'
for i in list_3:
df.loc[df.col1 == i, 'col2'] = 'C'
但是,这非常慢。数据帧为30,000行,每个列表包含大约5,000-10,000个项目,因此计算时间可能很长,尤其是与其他熊猫操作相比。有更好的(更快)方法吗?
答案 0 :(得分:6)
您可以在此处将isin
与np.select
一起使用:
df['col2'] = (np.select([df['col1'].isin(list_1),
df['col1'].isin(list_2),
df['col1'].isin(list_3)]
,['A','B','C']))
使用Map
:
d = dict(zip(map(tuple,[list_1,list_2,list_3]),['A','B','C']))
df['col2'] = df['col1'].map({val: v for k,v in d.items() for val in k})
col1 col2
0 1 A
1 2 A
2 6 C
3 5 C
4 9 C
5 3 B
6 5 C
答案 1 :(得分:4)
您可以先将列表转换成字典,然后再映射到col1。
d1 = {k:'A' for k in list_1}
d2 = {k:'B' for k in list_2}
d3 = {k:'C' for k in list_3}
df['col2'] = (
df.col1.apply(lambda x: d1.get(x,x))
.combine_first(df.col1.apply(lambda x: d2.get(x,x)))
.combine_first(df.col1.apply(lambda x: d2.get(x,x)))
)
如果列表中没有重复项,则可以通过将它们合并到一个字典中来使其更快:
d = {**{k:'A' for k in list_1},
**{k:'B' for k in list_2},
**{k:'C' for k in list_3}}
df['col2'] = df.col1.apply(lambda x: d.get(x,x))
答案 2 :(得分:1)
我建议使用条件更新用字典遍历您的列表:
# Create your update dictionary
col_dict = {
"A":[1, 2, 4],
"B":[3, 8],
"C":[5, 6, 7, 9]
}
# Iterate and update
for key, value in col_dict.items():
# key is the col name; value is the lookup list
df["col2"] = np.where(df["col1"].isin(value), key, df["col2"])
存在覆盖值的担忧-因为从技术上说一行可以匹配多个列表。这些更新的协调方式还不清楚。
如果行与多个键不匹配,请考虑采用动态编程方法,其中每次迭代均使用“未匹配”行的运行索引,并在进行时进行更新,以使迭代的行数更少每次迭代。