как определить тренд по уникальному ключу. dataframe - PullRequest
0 голосов
/ 28 августа 2018

У меня есть DataFrame с 2 столбцами

ColA| ColB 
D 2 
D 12 
D 15 
A 20 
A 40 
A 60 
C 60 
C 55 
C 70 
C 45 
L 45 
L 23 
L 10 
L 5 

РЕЗУЛЬТАТ / Выход будет

D UP
A UP
C FLAT
L Down 
Где UP - результат сложения всех соответствующих весов: каждый последующий вес для каждого ключа должен быть меньше предыдущего веса. пример для UP у вас должно быть

Ответы [ 5 ]

0 голосов
/ 28 августа 2018

Использование numpy.polyfit в пользовательском def

Таким образом, вы можете настроить градиент, который вы бы назвали «FLAT»

def trend(x, flat=3.5):
    m = np.polyfit(np.arange(1, len(x)+1), x, 1)[0]
    if abs(m) < flat:
        return 'FLAT'
    elif m > 0:
        return 'UP'
    return 'DOWN'

df.groupby('ColA')['ColB'].apply(np.array).apply(trend)
0 голосов
/ 28 августа 2018

Решение путем применения линейной регрессии к каждой точке, связанной с идентификатором, и определения тренда по наклону точки, связанной с идентификатором, в 2-мерном пространстве

import numpy as np
from sklearn import linear_model
def slope(x,min_slope,max_slope):
    reg = linear_model.LinearRegression()
    reg.fit(np.arange(len(x),x))
    slope =  reg.coef_[0][0]
    if slope < min_slope:
        return 'Down'
    if slope > max_slope:
         return 'Up'
    else 'Flat'
min_slope = -1
max_slope = 1
df['slopes'] = df.groupby('ColA').apply(lambda x: slope(x['ColB'],min_slope,max_slope))
0 голосов
/ 28 августа 2018

Использование diff и crosstab

s=df.groupby('ColA').ColB.diff().dropna()#Dropna since the first value for all group is invalid 
pd.crosstab(df.ColA.loc[s.index],s>0,normalize = 'index' )[True].map({1:'Up',0:'Down'}).fillna('Flat')
Out[100]:
ColA
A      Up
C    Flat
D      Up
L    Down
Name: True, dtype: object
0 голосов
/ 28 августа 2018

Вариация идеи @ Dark: сначала я вычислю GroupBy + diff, а затем использую unique перед передачей пользовательской функции.

Затем используйте логику, основанную на значениях min / max.

def calc_label(x):
    if min(x) >= 0:
        return 'UP'
    elif max(x) <= 0:
        return 'DOWN'
    else:
        return 'FLAT'

res = df.assign(C=df.groupby('ColA').diff().fillna(0))\
        .groupby('ColA')['C'].unique()\
        .apply(calc_label)

print(res)

ColA
A      UP
C    FLAT
D      UP
L    DOWN
Name: C, dtype: object
0 голосов
/ 28 августа 2018

Вот простая техника, которая может не подходить для всех случаев, т. Е.

def sum_t(x):
    # Compare the value with previous value
    m = x > x.shift() 
    # If all of them are increasing then return Up
    if m.sum() == len(m)-1:
        return 'UP'
    # if all of them are decreasing then return Down
    elif m.sum() == 0:
        return 'DOWN'
    # else return flat
    else:
        return 'FLAT'

df.groupby('ColA')['ColB'].apply(sum_t)

Выход:

ColA
A      UP
C    FLAT
D      UP
L    DOWN
Name: ColB, dtype: object
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...