pandas -groupby: применить пользовательскую функцию, которой требуется 2 столбца в качестве входных данных, чтобы получить один столбец в качестве выходных данных. - PullRequest
0 голосов
/ 14 июля 2020

У меня есть датафрейм с датами и значением за день. Я хочу увидеть градиент значения, если он растет, уменьшается, .... Лучший способ - применить линейную регрессию с днем ​​как x и значением как y:

import pandas as pd
df = pd.DataFrame({'customer':['a','a','a','b','b','b'],
                   'day':[1,2,4,2,3,4],
                   'value':[1.5,2.4,3.6,1.5,1.3,1.1]})

df:


  customer  day  value
0        a    1    1.5
1        a    2    2.4
2        a    4    3.6
3        b    2    1.5
4        b    3    1.3
5        b    4    1.1

Вручную я могу выполнить линейную регрессию:

from sklearn.linear_model import LinearRegression
def gradient(x,y):
    return LinearRegression().fit(x,y).coef_[0]

xa = df[df.customer =='a'].day.values.reshape(-1, 1)
ya = df[df.customer =='a'].value.values.reshape(-1, 1)
xb = df[df.customer =='b'].day.values.reshape(-1, 1)
yb = df[df.customer =='b'].value.values.reshape(-1, 1)
print(gradient(xa,ya),gradient(xb,yb))

result: [0.68571429] [-0.2]

Но я бы хотел использовать groupby как в

df.groupby('customer').agg({'value':['mean','sum','gradient']})

с выводом вида:

               value     
          mean  sum  gradient
customer           
a          2.5  7.5   0.685
b          1.3  3.9  -0.2

проблема в том, что для градиента требуется 2 столбца на входе.

1 Ответ

1 голос
/ 14 июля 2020

Вы можете сделать:

# calculate gradient
v =  (df
      .groupby('customer')
      .apply(lambda x: gradient(x['day'].to_numpy().reshape(-1, 1), 
                                x['value'].to_numpy().reshape(-1, 1)))
v.name = 'gradient'

# calculate mean, sum
d1 = df.groupby('customer').agg({'value': ['mean', 'sum']})

# join the results
d1 = d1.join(v)

# fix columns
d1.columns = d1.columns.str.join('')
print(d1)

               valuemean     valuesum  gradient
customer                                       
a                   2.5           7.5  0.685714
b                   1.3           3.9 -0.200000
...