Панды получают скользящие данные на основе прошлого года и создают столбцы в кадре данных - PullRequest
0 голосов
/ 12 января 2019

У меня есть фрейм данных с 3 столбцами, включая A, B, C. Мне нужно создать столбцы, используя столбцы B, C, как показано в разделе вывода ниже.

dataframe:

A       B        C      
C_1    pink     1971    
C_1    pink     1972    
C_1    blue     1972    
C_1    red      1973    
C_1    pink     1973    
C_1    white    1974    

выход:

Здесь для первой строки C-год - 1971, который является наименьшим, а количество столбцов b равно 1, поэтому для этой строки выходное значение должно быть 1 для B_cnt_C-0, а далее оно должно быть 0, поскольку мы не сообщаем информацию до 1971 г. но для 2-й и 3-й строк v имеют информацию для 1971 и 1972 гг., поэтому выходные данные должны быть такими, как показано ниже для 2-й и 3-й строк и той же процедурой для всех оставшихся строк.

A       B        C       B_cnt_C-0  B_cnt_C-1  B_cnt_C-2    B_cnt_C-3
C_1    pink     1971         1         0            0           0
C_1    pink     1972         2         1            0           0
C_1    blue     1972         2         1            0           0
C_1    red      1973         2         2            1           0
C_1    pink     1973         2         2            1           0
C_1    white    1974         1         2            2           1   

1 Ответ

0 голосов
/ 12 января 2019

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

#get number of unique values per groups
s = df.groupby(['A','C'])['B'].nunique()
#get max number of groups
a = df.groupby('A')['C'].nunique().max()
#shift per groups and join together
df1 = pd.concat([s.groupby(level=0).shift(x).fillna(0, downcast='int') 
                 for x in range(a)], axis=1)
#new columns names
df1.columns = ['B_cnt_C-{}'.format(x) for x in range(len(df1.columns))]
print (df1)
          B_cnt_C-0  B_cnt_C-1  B_cnt_C-2  B_cnt_C-3
A   C                                               
C_1 1971          1          0          0          0
    1972          2          1          0          0
    1973          2          2          1          0
    1974          1          2          2          1
#join to original
df = df.join(df1, on=['A','C'])
print (df)
     A      B     C  B_cnt_C-0  B_cnt_C-1  B_cnt_C-2  B_cnt_C-3
0  C_1   pink  1971          1          0          0          0
1  C_1   pink  1972          2          1          0          0
2  C_1   blue  1972          2          1          0          0
3  C_1    red  1973          2          2          1          0
4  C_1   pink  1973          2          2          1          0
5  C_1  white  1974          1          2          2          1

Решение с большим количеством групп:

print (df)
      A      B     C
0   C_1   pink  1971
1   C_1   pink  1972
2   C_1   blue  1972
3   C_1    red  1973
4   C_1   pink  1973
5   C_1  white  1974
6   C_2   pink  1975
7   C_2   pink  1976
8   C_3   blue  1976
9   C_3    red  1978
10  C_3   pink  1979
11  C_3  white  1979

s = df.groupby(['A','C'])['B'].nunique()
a = df.groupby('A')['C'].nunique().max()
df1 = pd.concat([s.groupby(level=0).shift(x).fillna(0, downcast='int') 
                 for x in range(a)], axis=1)

df1.columns = ['B_cnt_C-{}'.format(x) for x in range(len(df1.columns))]
df = df.join(df1, on=['A','C'])
print (df)
      A      B     C  B_cnt_C-0  B_cnt_C-1  B_cnt_C-2  B_cnt_C-3
0   C_1   pink  1971          1          0          0          0
1   C_1   pink  1972          2          1          0          0
2   C_1   blue  1972          2          1          0          0
3   C_1    red  1973          2          2          1          0
4   C_1   pink  1973          2          2          1          0
5   C_1  white  1974          1          2          2          1
6   C_2   pink  1975          1          0          0          0
7   C_2   pink  1976          1          1          0          0
8   C_3   blue  1976          1          0          0          0
9   C_3    red  1978          1          1          0          0
10  C_3   pink  1979          2          1          1          0
11  C_3  white  1979          2          1          1          0
...