对照另一个 DataFrame 的列表列检查一个 DataFrame 的列表列

Checking one DataFrame's Column of Lists Against Another DataFrame's Column of Lists

我有 2 个 DataFrame,每个都有一列列表。

我需要检查 df2 中的每个列表,看看 df1 中是否有包含其所有元素的列表。

即。 df2 第 1 行有一个列表 [1,5]。我需要检查 df1 的所有列表,看看是否有任何列表同时包含 1 和 5。

对于 df2 中具有完全匹配的任何列表,它们会在 df2['bucket'] 列中标记为 'clean'

我的问题:对于较大的数据集,目前速度非常慢。我希望有人可以提出更快的方法。

import pandas as pd

list1 = [
    ['a', [1, 5, 10, 14, 15]],
    ['l',  [7, 13, 25, 46, 50]],
    ['o',  [2, 4, 6, 19, 36]],
    ['d',  [1, 19, 24, 26, 29]]]

df1 = pd.DataFrame(list1, columns =['Fruits', 'Values']) 

list2 = [
    ['a', [1, 5]],
    ['r',  [2, 4, 5]],
    ['e',  [2, 9]],
    ['f',  [2, 6, 36]],
    ['w',  [2, 6, 37]],
    ['a',  [24, 29]],
    ['q',  [1, 14, 15]]]

df2 = pd.DataFrame(list2, columns =['Fruits', 'Values']) 

df1['bucket'] = ""


list1_row_count = df1.shape[0]
list2_row_count = df2.shape[0]

for x in range(list2_row_count):
    break_out = False
    for _ in range(list1_row_count):
        if break_out == True : break
        df1_list = df1['Values'].iloc[_]
        df2_list = df2['Values'].iloc[x]
        check =  all(item in df1_list for item in df2_list)
        

        if check is True:
            df2.loc[x, 'bucket'] = 'clean'
            break_out = True
        else :
            df2.loc[x, 'bucket'] = 'mixed'


print(df1)
print('')
print(df2)

你可以尝试使用to_numpy(),速度相当快:

def process(a, b):
  def compare(a, i):
    idx = 0
    while idx < a.shape[0]:
      if all(x in a[idx] for x in i): return 'clean'  
      idx +=1
    return 'mixed'
  return [compare(a, i) for i in b]

df2['bucket'] = process(df1.Values.to_numpy(), df2.Values.to_numpy())
  Fruits       Values bucket
0      a       [1, 5]  clean
1      r    [2, 4, 5]  mixed
2      e       [2, 9]  mixed
3      f   [2, 6, 36]  clean
4      w   [2, 6, 37]  mixed
5      a     [24, 29]  clean
6      q  [1, 14, 15]  clean

@AloneTogether 的解决方案应该已经显着缩短了代码的运行时间。我认为您可以使用集合操作来进一步改进运行时间。

基本上,您可以将每个子列表转换为一个集合并使用 set.issubset 迭代地检查 df1['Value'] 中的任何列表是否是 df2['Value'] 中任何列表的子集:

def process(a, b):
    def compare(a, i):
        for s in a:
            if i.issubset(s):
                return 'clean'
        return 'mixed'
    return [compare(a, i) for i in b]

df2['bucket'] = process([*map(set, df1['Values'])], map(set, df2['Values']))

运行时(在您提供的示例中):

你的:

7.08 ms ± 391 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

@AloneTogether:

273 µs ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

我的:

233 µs ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)