Python 检查一个df中的值是否在第二个df列的列表中
我有两个数据帧 df1:有4列,每列都有一个包含值的列表 df2:有一列(列)该列有1个值 我想检查df2(col)中的任何值是否在df1(col1)或df1(col2)行中的任何列表中,然后保存该行(df1和4列) 下面是一些随机数据作为示例:Python 检查一个df中的值是否在第二个df列的列表中,python,pandas,performance,dataframe,optimization,Python,Pandas,Performance,Dataframe,Optimization,我有两个数据帧 df1:有4列,每列都有一个包含值的列表 df2:有一列(列)该列有1个值 我想检查df2(col)中的任何值是否在df1(col1)或df1(col2)行中的任何列表中,然后保存该行(df1和4列) 下面是一些随机数据作为示例: df1 = pd.DataFrame({'col1': [[32, 24, 5, 6], [4, 8, 14], [12, 32, 234, 15, 6], [45]],
df1 = pd.DataFrame({'col1': [[32, 24, 5, 6], [4, 8, 14],
[12, 32, 234, 15, 6], [45]],
'col2': [[13, 333 ,5], [32, 28, 5, 9],
[4], [12, 45, 21]],
'col3': [['AS', 'EWE', 'SADF', 'EW'],
['EW', 'HHT', 'IYT'], ['C', 'KJG', 'TF', 'VC', 'D'], ['BX']],
'col4': [['HG', 'FDGD' ,'F'], ['FDG', 'Y', 'FS', 'RT'],
['T'], ['XC', 'WE', 'TR']]
})
df2 = pd.DataFrame({'col': [1, 333, 8, 11, 45]})
df1:
df2:
这段代码运行得很好,但我使用的是大数据,所以需要花很多时间才能完成。
所以我想知道是否有任何方法可以优化它
for index, row in df1.iterrows():
if (any(itm in row['col1'] for itm in df2['col'])):
df3 = df3.append(row)
elif (any(itm in row['col2'] for itm in df2['col'])):
df3 = df3.append(row)
这就是输出的样子:
col1 col2 col3 col4
0 [32, 24, 5, 6] [13, 333, 5] [AS, EWE, SADF, EW] [HG, FDGD, F]
1 [4, 8, 14] [32, 28, 5, 9] [EW, HHT, IYT] [FDG, Y, FS, RT]
3 [45] [12, 45, 21] [BX] [XC, WE, TR]
输出可以是新的df,也可以是df1中带有“1”或“0”的列(如果值不在这两列中的任何一列中)
更新:
遵循cs95方法,我能够提高代码的性能
我以前的代码需要55秒,而他的方法只有8毫秒,因此大约需要x690的加速。当然,我们可以使用设置查找来加速:
lookup = {*df2['col']}
df1[~df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)]
col1 col2 col3 col4
0 [32, 24, 5, 6] [13, 333, 5] [AS, EWE, SADF, EW] [HG, FDGD, F]
1 [4, 8, 14] [32, 28, 5, 9] [EW, HHT, IYT] [FDG, Y, FS, RT]
3 [45] [12, 45, 21] [BX] [XC, WE, TR]
处理列表列很难。通过识别,我们可以使用applymap
,因为df1['col1']
和df1['col2']
中的每个单元格都必须进行相同的检查(在df2['col']
上进行查找)。然后使用一点布尔逻辑来确定要删除哪些行,您就得到了最终结果
使用iterrows
和append
时,您的代码会受到双重打击。永远不要在数据帧上迭代,因为它很慢并且浪费内存,永远不要因为同样的原因增长数据帧
当然,我们可以使用设置查找来加快速度:
lookup = {*df2['col']}
df1[~df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)]
col1 col2 col3 col4
0 [32, 24, 5, 6] [13, 333, 5] [AS, EWE, SADF, EW] [HG, FDGD, F]
1 [4, 8, 14] [32, 28, 5, 9] [EW, HHT, IYT] [FDG, Y, FS, RT]
3 [45] [12, 45, 21] [BX] [XC, WE, TR]
处理列表列很难。通过识别,我们可以使用applymap
,因为df1['col1']
和df1['col2']
中的每个单元格都必须进行相同的检查(在df2['col']
上进行查找)。然后使用一点布尔逻辑来确定要删除哪些行,您就得到了最终结果
使用iterrows
和append
时,您的代码会受到双重打击。永远不要在数据帧上迭代,因为它很慢并且浪费内存,永远不要因为同样的原因增长数据帧
您好,谢谢您的接受。修改后的解决方案的加速系数是多少?您好,谢谢您的帮助!我将更多地研究如何编写更高效的代码。加速系数约为X690您好,感谢您的接受。修改后的解决方案的加速系数是多少?您好,谢谢您的帮助!我将更多地研究如何编写更高效的代码。加速系数约为x690
lookup = {*df2['col']}
df1[~df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)]
col1 col2 col3 col4
0 [32, 24, 5, 6] [13, 333, 5] [AS, EWE, SADF, EW] [HG, FDGD, F]
1 [4, 8, 14] [32, 28, 5, 9] [EW, HHT, IYT] [FDG, Y, FS, RT]
3 [45] [12, 45, 21] [BX] [XC, WE, TR]
lookup
# {1, 8, 11, 45, 333}
# get cells that have no elements in common
df1[['col1', 'col2']].applymap(lookup.isdisjoint)
col1 col2
0 True False
1 False True
2 True True
3 False False
# get rows who have no columns in common
df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)
0 False
1 False
2 True
3 False
dtype: bool
# invert the condition to get rows to keep
~df1[['col1', 'col2']].applymap(lookup.isdisjoint).all(axis=1)
0 True
1 True
2 False
3 True
dtype: bool