将多列与具有多个值的列表进行比较
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
df1
和df2
有相同的行数(实际数据有100万)并且df2
的每一行由方括号中的几个数字组成,逗号分隔如下:
df2 = pd.DataFrame({
"0": [[1123, 2021, 8788]]})
方括号中的数字从1到20不等,在本例中只有3。但是,df2
和df1
的数字行是相同的。
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]
我有这个数据。
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
df1
和df2
有相同的行数(实际数据有100万)并且df2
的每一行由方括号中的几个数字组成,逗号分隔如下:
df2 = pd.DataFrame({
"0": [[1123, 2021, 8788]]})
方括号中的数字从1到20不等,在本例中只有3。但是,df2
和df1
的数字行是相同的。
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]