检查列表是否是熊猫数据框中另一个列表的子集

Lev*_*osa 4 python pandas

所以,我有这个包含近 3000 行的数据框,看起来像这样:

        CITIES
0       ['A','B']
1       ['A','B','C','D']
2       ['A','B','C']
4       ['X']
5       ['X','Y','Z']
...     ...
2670    ['Y','Z']
Run Code Online (Sandbox Code Playgroud)

我想从 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
Run Code Online (Sandbox Code Playgroud)

有没有更有效的方法来做到这一点?

ALo*_*llz 6

首先创建虚拟数据帧,然后我们可以使用矩阵乘法来查看其中一行是否是另一行的完整子集,方法是检查与另一行的乘法和是否等于该行中的元素数。(将是一个内存密集型)

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']]})    
Run Code Online (Sandbox Code Playgroud)
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]
Run Code Online (Sandbox Code Playgroud)

如果您有两行与最长的子集并列,(即两行带有 ['A','B','C','D'])都将被删除。如果不希望你可以先drop_duplicates'Cities'(需要隐蔽的哈希的类型一样frozenset),然后应用上面。