Парные операции в Scikit-Learn и различные условия фильтрации для каждой пары - PullRequest
0 голосов
/ 13 марта 2020

У меня есть следующие 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 против 1 2 3 в качестве столбца a имеет 0

Сравнение 2

4 0 0 7 против 5 1 2 3 сделано на 4 7 против 5 3, поскольку у нас есть 2 столбца, которые нужно отбросить

Сравнение 3

8 9 10 11 против 5 1 2 3 выполняется на 8 9 10 11 против 5 1 2 3, поскольку столбцы не отбрасываются

Сравнение 4

0 0 0 15 против 5 1 2 3 выполняется 15 против 3, так как отбрасываются все столбцы, кроме одного

Результатом каждой парной операции является скаляр, поэтому результатом является некая структура, будь то список, массив , фрейм данных, независимо от 4 (или количества строк в df1) значений. Кроме того, я должен отметить, что значения в df2 не имеют значения, и фильтрация не выполняется на основе значения любого столбца в df2.

1 Ответ

1 голос
/ 13 марта 2020

Для простоты, вы можете попробовать зациклить каждую строку в кадре данных и сделать что-то вроде этого:

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)])

Здесь я использовал парное сложение, но вы могли бы заменить сложение на операцию по вашему выбору. .

Редактировать: Мы можем захотеть векторизовать это, чтобы избежать l oop, если кадры данных большие. Вот идея для этого, где мы конвертируем нулевые значения в 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
...