将多列与具有多个值的列表进行比较

Comparing multiple columns to a list with multiple values

我有这个数据。

df1 = pd.DataFrame({"user": [1942,  95870, 85228,  6636],
                   "0": [1524, 8788, 9899, 27172],
                   "1": [1333, 4476, 78783, 90832],
                   "2": [2021, 2022, 34522, 38479]})
df1.set_index(df1['user'])
print(df1)

    user      0      1      2
0   1942   1524   1333   2021
1  95870   8788   4476   2022
2  85228   9899  78783  34522
3   6636  27172  90832  38479

df1df2有相同的行数(实际数据有100万)并且df2的每一行由方括号中的几个数字组成,逗号分隔如下:

df2 = pd.DataFrame({
                   "0": [[1123, 2021, 8788]]})

方括号中的数字从1到20不等,在本例中只有3。但是,df2df1的数字行是相同的。

print(df2)
           0
0  [1123, 2021, 8788]

我想做的是从 df1 中挑选一个用户,例如 user1942 并比较该行 (1524, 1333, 2021) 中的三个数字中的任何一个是否在任何一个df2 [1123, 2021, 8788] 中相应的方括号。如果为真则为 1 的布尔值,否则为 0,或任何其他表示形式都会有所帮助。

更新:应该逐行比较。这是 df1 中的一行与 df2 中的对应行。

输出可能看起来像这样,或者更接近: 输出:由于 2021 在 df2 中,答案为 True。然后移动到df1中的下一个用户,将该用户的3个数字与df2中相应的行号进行比较,依此类推

user      status
1942        1
...

我知道有很多关于比较多列的问题,但我找不到可重现或与此上下文类似的内容。

假设 df1 的索引与 df2 的索引相同,并且两者的行之间的关系是 1:1,我会这样做:

df3 = pd.DataFrame()
  for index, row in df1.iterrows():
  to_find = [row[1], row[2], row[3]]
  to_check = df2.iloc[index][0]
  if [True for i in to_find if i in to_check]:
    df3 = df3.append([1])
  else:
    df3 = df3.append([0])

您为 df1 中的值创建一个列表,然后检查是否有任何值出现在相应 df2 行的列表中,如果至少有一个值匹配,您将 1 附加到结果 df3,否则为 0。 始终假设您的关系是 1:1,现在在 df3 中,您拥有与所选用户对应的索引和用于验证匹配的布尔值。

编辑:改进 Daniele 的解决方案以允许对整数进行迭代

df3 = pd.DataFrame()
for index, row in df1.iterrows():
    to_find = [row[0], row[1], row[2], row[3]]
    to_check = df2.iloc[index][0]
    to_numpy = np.array([to_check])
    to_list  = to_numpy.tolist()
    if [True for i in to_find if i in to_list]:
        df3 = df3.append([1])
    else:
        df3 = df3.append([0])

我还没有找到一个不依赖 for 循环的非常优雅的解决方案,但是如果我们首先将数据帧转换为 np.arrays(甚至列表),我们可以获得一个非常好的解决方法。 首先,我们操作 df1 来获取有组织的记录

import pandas as pd
import numpy as np

df1 = pd.DataFrame({"user": [1123,  95870, 85228,  6636],
                   "0": [1524, 8788, 9899, 27172],
                   "1": [1333, 4476, 78783, 90832],
                   "2": [2021, 2022, 34522, 38479]})
df1 = df1.set_index('user', drop=True)
print(df1)
           0      1      2
user                      
1123    1524   1333   2021
95870   8788   4476   2022
85228   9899  78783  34522
6636   27172  90832  38479

然后,我们对df2做同样的事情。即使两个数据帧具有不同的列数,所提出的方法也适用。

df2 = pd.DataFrame([[1123, 2021, 8788, 6636],
                    [1333, 2023, 4477, 78783],
                    [1524, 2023, 9899, 27172],
                    [2021, 2023, 345233,38479]]
                    )

df2 = pd.DataFrame(df2.to_numpy().tolist())
df2 = df2.set_axis(df1.index, axis=0)
print(df2)
          0     1       2      3
user                            
1123   1123  1333    8788   6636
95870  1333  2023    4477  78783
85228  1524  2023    9899  27172
6636   2021  2023  345233  38479

最后,我们使用遍历行以检查它们是否具有共同元素的列表理解生成所需的值。

inter = [np.isin(arr[0], arr[1]).any() for arr in zip(df1.to_numpy(), df2.to_numpy())]
print(inter)
[True, False, True, True]