pandas значения данных в кадре в одной строке по весам - PullRequest
0 голосов
/ 12 апреля 2020

это похоже на базовый c вопрос, но элегантное решение ускользает от меня.

У меня есть pandas фрейм данных, где все значения были назначены в одну строку. Однако мне нужно разделить значения по нескольким строкам по весам. Пример здесь:

Кадр входных данных:

import pandas as pd

# starting df with weights W.
df_input = pd.DataFrame({
    'W': [0.3, 0.2, 0.5],
    'X1': [100, 0, 0],
    'X2': [150, 0, 0],
    'X3': [200, 0, 0],
    'X4': [300, 0, 0]
})

Требуемый кадр выходных данных:

df_output = pd.DataFrame({
    'W': [0.3, 0.2, 0.5],
    'X1': [30, 20, 50],
    'X2': [45, 30, 75],
    'X3': [60, 40, 100],
    'X4': [90, 60, 150]
})

Снимок экрана:

enter image description here

Ответы [ 6 ]

2 голосов
/ 12 апреля 2020

Чисто pandas решение:

df_output = df_input.copy()
df_output.loc[:, 'X1':] = df_output.loc[:, 'X1':].apply(lambda col: col[0] * df_output['W'])

Или использование numpy вещания:

df_output = df_input.copy()
df_output.loc[:, 'X1':] = df_output.loc[0, 'X1':].values[None, :] * df_output['W'].values[:, None]
1 голос
/ 12 апреля 2020

Вот альтернатива уже полученным отличным ответам:

Получить столбцы только для x:

x_columns = df_input.filter(like='X').columns

Вычислить (пояснения включены в комментарии):

df_input.loc[:,x_columns] = (df_input.loc[:,x_columns]
                            #spill the non zero values downwards
                            .replace(0,method='ffill')
                            #multiply by the 'W' column
                            .mul(df_input['W'],axis=0)
                            .astype(int)
                            )


     W  X1  X2  X3  X4
0   0.3 30  45  60  90
1   0.2 20  30  40  60
2   0.5 50  75  100 150
1 голос
/ 12 апреля 2020

Вывод данных в numpy массивы, затем вычисление точечного произведения

  • Создание двух массивов из данных строки и столбца
  • Формирование массивов
  • np.dot два массива
import pandas as pd
import numpy as np

# using your data

# weight
w = df_input.iloc[:, 0].to_numpy().reshape(len(df_input), 1)

array([[0.3],
       [0.2],
       [0.5]])

# values
v = df_input.iloc[0, 1:].to_numpy().reshape(1, len(df_input.columns[1:]))

array([[30., 45., 60., 90.]])

# load dot product into a dataframe
df_out = pd.DataFrame(np.dot(w, v))

# add column names
df_out.columns = df_input.columns[1:]

# insert W if needed
df_out.insert(0, 'W', df_input['W'])

# output
   W    X1    X2     X3     X4
 0.3  30.0  45.0   60.0   90.0
 0.2  20.0  30.0   40.0   60.0
 0.5  50.0  75.0  100.0  150.0
1 голос
/ 12 апреля 2020

Используя DataFrame.ffill для заполнения значений в вашем столбце, затем умножьте их на коэффициенты с помощью DataFrame.multiply

values = df_input.replace(0, np.NaN).ffill()
df_input.iloc[:, 1:] = values.iloc[:, 1:].mul(df_input['W'], axis=0)

Или мы можем использовать numpy, но сначала нам нужно изменить форму наш массив до (,1)

values = df_input.replace(0, np.NaN).ffill()
df_input.iloc[:, 1:] = values.iloc[:, 1:] * values['W'].to_numpy()[:, None]

     W    X1    X2     X3     X4
0  0.3  30.0  45.0   60.0   90.0
1  0.2  20.0  30.0   40.0   60.0
2  0.5  50.0  75.0  100.0  150.0
1 голос
/ 12 апреля 2020

Элегантность субъективна - возможен способ использования pd.clip

 for col in ['X1', 'X2', 'X3', 'X4']:
     df_input[col] = df_input[col].clip(lower=df_input[col].max())
     df_input[col]*=df_input['W']

Результат будет выше.

0 голосов
/ 12 апреля 2020

Если я правильно понимаю, это просто матричное умножение. Где вы начинаете с (3,1) матрицы и умножаете на (1,3). Конечный результат будет (3,3). Дайте мне знать, поможет ли этот обходной путь каким-либо образом:

import numpy as np
A = np.array([[3,6,7],[5,-3,0]])
B = np.array([[1,1],[2,1],[3,-1]])
C = A.dot(B)
print (C)

Output:
[[36,-12],
 [-1,  2] 
...