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
我有以下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