如何解决将使用 .loc 创建新列的 for 循环加速到更快的方法中?
我一直在使用以下方法根据满足多个列表中多个条件的每一行将值分配给新列。它适用于小型 dfs...但是一旦我处理更大的数据,就需要永远。
for i,j,k in zip(list1,list2,list3):
df.loc[((df['foo'] == i) & (df['bar'] == j)),'new_column'] = k
示例数据:
list1 = ['a','a','e','f','c']
list2 = [3,4,5,3,2]
list3 = ['yellow','green','blue','purple','orange','black']
df = pd.dataframe({'foo': ['a','b','c','d','c'],'bar': [3,2,2]})
所以基本上对于新列,我需要:
- 第一行标记为黄色(因为 list1=a & list2=3)
- 第三行标记为黑色(因为 list1=c & list2=2)
- 第 5 行标记为蓝色(因为 list1=e & list2=5)
- 第 6 行标记为橙色(因为 list1=f & list2=3)
- 第 7 行标记为黑色(因为 list1=c & list2=2)
所有列表的长度都相同。我已经搜索了 Stack 以获得更好的选择,所以我知道一个选项是列表理解(或其他),但不确定如何将其与 .loc 结合并创建一个新列。
提前感谢您的帮助!!
解决方法
想法是将 zip
与 DataFrame
辅助函数一起使用,因此可以将 DataFrame.merge
与左连接一起使用:
df1 = pd.DataFrame(zip(list1,list2,list3),columns=['foo','bar','new_column'])
print (df1)
foo bar new_column
0 a 3 yellow
1 a 4 green
2 e 5 blue
3 f 3 purple
4 c 2 orange
df = df.merge(df1,how='left',on=['foo','bar'])
print (df)
foo bar new_column
0 a 3 yellow
1 b 2 NaN
2 c 2 orange
3 d 4 NaN
4 e 5 blue
5 f 3 purple
6 c 2 orange
,
看起来您正在尝试实现等效于此处的连接操作。以下应该为您提供相同的结果并使用数据帧操作,因此可能比循环列表更快。
(我从您的示例中删除了“紫色”)
list3 = ['yellow','green','blue','orange','black']
从您的列表中构建一个数据框并加入条件 (foo = i & bar = j):
joiner = pd.DataFrame({"i": list1,"j": list2,"k": list3})
df.join(joiner.set_index(["i","j"]),on=["foo","bar"])
给予:
foo bar k
0 a 3 yellow
1 b 2 NaN
2 c 2 black
3 d 4 NaN
4 e 5 blue
5 f 3 orange
6 c 2 black
请注意,如果您有重复的匹配项,每个 (i,j) 匹配项都会有一个重复的 (foo,bar) 行。您需要对数据帧进行重复数据删除以获得与循环代码相同的结果,并且加入的数据帧可能会变得非常大。我猜想,因为您的代码总是会覆盖任何重复项,所以这并不常见?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。