所以,我有这个包含近 3000 行的数据框,看起来像这样:
CITIES
0 ['A','B']
1 ['A','B','C','D']
2 ['A','B','C']
4 ['X']
5 ['X','Y','Z']
... ...
2670 ['Y','Z']
我想从 DF 中删除“CITIES”列表包含在另一行中的所有行(顺序无关紧要),在上面的示例中,我想删除 0 和 2,因为两者都包含在 1 中,并删除 4 和 2670,因为两者都包含在内,我尝试了一些东西,它有点工作,但它真的很愚蠢,花了将近 10 分钟来计算,就是这样:indexesToRemove=[]
for index, row in entrada.iterrows():
citiesListFixed=row['CITIES']
for index2, row2 in entrada.iloc[index+1:].iterrows():
citiesListCurrent=row2['CITIES']
if set(citiesListFixed) <= set(citiesListCurrent):
indexesToRemove.append(index)
break
有没有更有效的方法来做到这一点?
最佳答案
首先创建虚拟数据帧,然后我们可以使用矩阵乘法来查看其中一行是否是另一行的完整子集,方法是检查与另一行的乘法和是否等于该行中的元素数。 (将是一个内存密集型)
import pandas as pd
import numpy as np
df = pd.DataFrame({'Cities': [['A','B'], ['A','B','C','D'], ['A','B','C'],
['X'], ['X','Y','Z'], ['Y','Z']]})
arr = pd.get_dummies(df['Cities'].explode()).max(level=0).to_numpy()
#[[1 1 0 0 0 0 0]
# [1 1 1 1 0 0 0]
# [1 1 1 0 0 0 0]
# [0 0 0 0 1 0 0]
# [0 0 0 0 1 1 1]
# [0 0 0 0 0 1 1]]
subsets = np.matmul(arr, arr.T)
np.fill_diagonal(subsets, 0) # So same row doesn't exclude itself
mask = ~np.equal(subsets, np.sum(arr, 1)).any(0)
df[mask]
# Cities
#1 [A, B, C, D]
#4 [X, Y, Z]
如果你有两行与最长的子集相关联,(即两行带有
['A','B','C','D']
)都被删除了。如果这不是您想要的,您可以先 drop_duplicates
在 'Cities'
(需要转换为可散列类型,如 frozenset
),然后应用上述内容。
关于python - 检查列表是否是 Pandas 数据框中另一个列表的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66066357/