我正在使用Python 3.7.7和Pandas 1.1.3。
我有两个 Pandas 数据库df1
和df2
具有相同的列名,可以按list(df1.columns)
或list(df2.columns)
列出。它们的长度是len(list(df1.columns)) = 200
.
我想查找df2
中第一个 10 个值与df1
第i
行中的值匹配的所有行。
我知道这可以通过以下方式完成:
colnames = list(df1.columns[:10]) # lists the first 10 column names
toFind = list(df1.iloc[i][:10]) # lists the first 10 values in the i'th row of df1
df2.loc[(df2[colnames[0]] == toFind[0]) & (df2[colnames[1]] == toFind[1]) & (df2[colnames[2]] == toFind[2]) & (df2[colnames[3]] == toFind[3]) & (df2[colnames[4]] == toFind[4]) & (df2[colnames[5]] == toFind[5]) & (df2[colnames[6]] == toFind[6]) & (df2[colnames[7]] == toFind[7]) & (df2[colnames[8]] == toFind[8]) & (df2[colnames[9]] == toFind[9])]
然而,这是非常漫长且难以改变的。如果我想按不同数量的匹配索引(10 个除外)进行过滤,我每次都必须重写整个表达式。
有没有办法自动执行此操作?我正在寻找类似的东西
colnames = list(df1.columns[:10])
toFind = list(df1.iloc[i][:10])
df2.loc[(df2[colnames[t]] == toFind[t]) for t in range(len(colnames))]
但是,这显然会返回一个错误,因为在 Pandas 中没有实现这样的东西。
示例:(为简单起见,我将使用 3 而不是 10,并设置i=0
)
df1:
i col1 col2 col3 col4 col5 col6 col7
0 1 7 3 4 8 2 4
1 2 5 7 1 4 8 2
2 6 6 8 8 9 1 3
3 7 8 5 2 3 0 9
4 4 0 7 4 5 6 3
5 2 7 6 8 1 7 5
df2:
i col1 col2 col3 col4 col5 col6 col7
0 1 7 3 3 3 4 5
1 2 5 7 5 5 2 5
2 1 7 3 6 6 4 2
3 3 5 7 7 7 6 4
4 1 7 3 8 8 2 3
5 2 5 7 3 9 0 6
然后我想选择1 7 3
前 3 个值的所有df2
行(与df1
第0
行的前 3 个值相同)。那将是
filtered df2 (0):
i col1 col2 col3 col4 col5 col6 col7
0 1 7 3 3 3 4 5
2 1 7 3 6 6 4 2
4 1 7 3 8 8 2 3
如您所见,它过滤了df2
行,其中前 3 个值1 7 3
如果改为i=1
,那么我想过滤前 3 个值2 5 7
的df2
行(与df1
1
行的前 3 个值相同)
在这种情况下,输出将是
filtered df2 (1):
i col1 col2 col3 col4 col5 col6 col7
1 2 5 7 5 5 2 5
5 2 5 7 3 9 0 6
前面提到的 3 个,控制我过滤的列也是一个参数,在前面的示例中,它控制了col1 col2 col3
,在我的第一个解释中它是 10,它控制了col1 col2 ... col10
通常,它可以是列的任何列表,例如[col5 col7 col8 col15]
.
您可以使用np.logical_and.reduce
:
i = 0
colnames = list(df1.columns[:3])
toFind = list(df1.iloc[i][:3])
mask = np.logical_and.reduce([(df2[colnames[t]]==toFind[t]) for t in range(len(colnames))])
df = df2[mask]
print (df)
col1 col2 col3 col4 col5 col6 col7
i
0 1 7 3 3 3 4 5
2 1 7 3 6 6 4 2
4 1 7 3 8 8 2 3
另一个想法是使用:
i = 0
colnames = list(df1.columns[:3])
toFind = list(df1.iloc[i][:3])
df = df2[df2[colnames].eq(toFind).all(axis=1)]
print (df)
col1 col2 col3 col4 col5 col6 col7
i
0 1 7 3 3 3 4 5
2 1 7 3 6 6 4 2
4 1 7 3 8 8 2 3