Scikit-Learn 中的成对操作和每对的不同过滤条件

Pairwise operations in Scikit-Learn and different filtering conditions on each pair

我有以下2个数据框,比如df1

    a   b   c   d
0   0   1   2   3
1   4   0   0   7
2   8   9  10  11
3   0   0  0  15

和 df2

    a   b   c   d
0   5   1   2   3

我感兴趣的是对 df1 中的每一行和 df2 中的单行进行成对运算。但是,如果 df1 的一行中的某一列为 0,则该列既不会用于 df1 行也不会用于 df2 行来执行成对运算。因此,每个成对操作都适用于不同长度的行对。让我分解一下 4 比较应该如何。

比较 1

0 1 2 3 对比 5 1 2 3 成对运算是在 1 2 3 vs 1 2 3 上完成的,因为列 a 有一个 0

比较 2

4 0 0 7 vs 5 1 2 3 在 4 7 vs 5 3 上完成,因为我们有 2 列需要删除

比较 3

8 9 10 11 vs 5 1 2 3 在 8 9 10 11 vs 5 1 2 3 上完成,因为没有删除任何列

比较 4

0 0 0 15 vs 5 1 2 3 在 15 vs 3 上完成,因为除一列外的所有列都被删除

每个成对运算的结果都是一个标量,因此结果是某种结构,无论是列表、数组、数据框,还是具有 4(或 df1 中的行数)值的任何结构。另外,我应该注意到 df2 中的值是无关紧要的,并且不会根据 df2 中任何列的值进行过滤。

为简单起见,您可以尝试遍历数据框中的每一行并执行如下操作:

import pandas as pd
import numpy as np

a = pd.DataFrame(data=[[0,1,2,3],[4,0,0,7],[8,9,10,11],[0,0,0,15]], columns=['a', 'b', 'c', 'd'])
b = pd.DataFrame(data=[[5, 1, 2, 3]], columns=['a', 'b', 'c', 'd'])

# loop over each row in 'a'
for i in range(len(a)):
    # find indicies of non-zero elements of the row
    non_zero = np.nonzero(a.iloc[i].to_numpy())[0]

   # perform pair-wise addition between non-zero elements in 'a' and the same elements in 'b'
    print(np.array(a.iloc[i])[(non_zero)] +  np.array(b.iloc[0])[(non_zero)])

此处我使用了成对加法,但您可以将加法替换为您选择的运算。

编辑: 如果数据帧很大,我们可能希望对其进行矢量化以避免循环。这是一个想法,我们将零值转换为 nan 以便在行操作中忽略它们:

import pandas as pd
import numpy as np

a = pd.DataFrame(data=[[0,1,2,3],[4,0,0,7],[8,9,10,11],[0,0,0,15]], columns=['a', 'b', 'c', 'd'])
b = pd.DataFrame(data=[[5, 1, 2, 3]], columns=['a', 'b', 'c', 'd'])

# find indicies of zeros
zeros = (a==0).values

# set zeros to nan
a[zeros] = np.nan

# tile and reshape 'b' so its the same shape as 'a'
b = pd.DataFrame(np.tile(b, len(a)).reshape(np.shape(a)), columns=b.columns)
# set the zero indices to nan
b[zeros] = np.nan

print('a:')
print(a)

print('b:')
print(b)

# now do some row-wise operation. For example take the sum of each row
print(np.sum(a+b, axis=1))

输出:

a:
     a    b     c   d
0  NaN  1.0   2.0   3
1  4.0  NaN   NaN   7
2  8.0  9.0  10.0  11
3  NaN  NaN   NaN  15
b:
     a    b    c  d
0  NaN  1.0  2.0  3
1  5.0  NaN  NaN  3
2  5.0  1.0  2.0  3
3  NaN  NaN  NaN  3
sum:
0    12.0
1    19.0
2    49.0
3    18.0
dtype: float64