(Python/Pandas)如何按多个条件自动过滤行(也许使用列表理解)?



我正在使用Python 3.7.7和Pandas 1.1.3。

我有两个 Pandas 数据库df1df2具有相同的列名,可以按list(df1.columns)list(df2.columns)列出。它们的长度是len(list(df1.columns)) = 200.

我想查找df2第一个 10 个值与df1i行中的值匹配的所有行。

我知道这可以通过以下方式完成:

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行(与df10行的前 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 7df2行(与df11行的前 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

最新更新