Создание переменных и вычисление разницы между этими переменными и выбранной переменной - Pandas - PullRequest
2 голосов
/ 23 сентября 2019

У меня есть этот фрейм данных:

ID  Date        X   123_P   456_P   789_P   choice
A   07/16/2019  .   1.5     1.8     1.6     123
A   07/17/2019  .   2.0     2.1     4.5     789
A   07/18/2019  .   3.0     3.2     NaN     0
A   07/19/2019  .   2.1     2.2     4.5     456
B   07/16/2019  .   1.5     1.8     1.6     789
B   07/17/2019  .   2.0     2.1     4.5     0
B   07/18/2019  .   3.0     3.2     NaN     123

Я хочу создать новые переменные: 123_PD, 456_PD, 789_PD (у меня гораздо больше переменных, чем в этом примере, поэтому это не следует делать вручную).

Новые переменные будут обозначать различия между переменными 123_P, 456_P, 789_P и теми же переменными из предыдущей строки, с учетом предыдущего выбора .

Я имею в виду, если выбор из предыдущей строки был "123", то различия между этими переменными будут относиться к значению в "123_P" из предыдущей строки.

Примечания:

  • Значение 0 означает, что выбора нет, поэтому различия будут относиться к последнему выбору этого идентификатора.
  • Это должно быть сделано для каждого ID отдельно.

Ожидаемый результат:

ID  Date        X   123_P   456_P   789_P   choice  123_PD  456_PD  789_PD
A   07/16/2019  .   1.5     1.8     1.6     123     0       0       0
A   07/17/2019  .   2.0     2.1     4.5     789     0.5     0.6     3.0
A   07/18/2019  .   3.0     3.2     NaN     0       -1.5    -1.3    NaN
A   07/19/2019  .   2.1     2.2     4.5     456     -2.4    -2.3    0
B   07/16/2019  .   1.5     1.8     1.6     789     0       0       0
B   07/17/2019  .   2.0     2.1     4.5     0       0.4     0.5     2.9
B   07/18/2019  .   3.0     3.2     NaN     123     1.4     1.6     NaN

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Сначала создайте вспомогательный DataFrame с новым столбцом 0_P для заполненных пропущенных значений и измените choice значения для имен сопоставляемых столбцов:

df1 = (df.join(pd.DataFrame({'0_P':np.nan}, index=df.index))
         .assign(choice = df['choice'].astype(str) + '_P'))

print (df1)
  ID        Date  X  123_P  456_P  789_P choice  0_P
0  A  07/16/2019  .    1.5    1.8    1.6  123_P  NaN
1  A  07/17/2019  .    2.0    2.1    4.5  789_P  NaN
2  A  07/18/2019  .    3.0    3.2    NaN    0_P  NaN
3  A  07/19/2019  .    2.1    2.2    4.5  456_P  NaN
4  B  07/16/2019  .    1.5    1.8    1.6  789_P  NaN
5  B  07/17/2019  .    2.0    2.1    4.5    0_P  NaN
6  B  07/18/2019  .    3.0    3.2    NaN  123_P  NaN

Затем используйте DataFrame.lookup для значенийв массив, преобразовать в Series, Series.shift и заполнить пропущенные значения по группам в лямбда-функции вперед:

s = (pd.Series(df1.lookup(df1.index, df1['choice']), index=df.index)
       .groupby(df['ID'])
       .apply(lambda x: x.shift().ffill()))
print (s)
0    NaN
1    1.5
2    4.5
3    4.5
4    NaN
5    1.6
6    1.6
dtype: float64

Затем выбрать необходимые столбцы, вычесть на DataFrame.sub, DataFrame.add_suffix и последние заданные строки равны 0 по дублированному столбцу ID:

df2 = df.iloc[:, -4:-1].sub(s, axis=0).add_suffix('D')
df2.loc[~df1['ID'].duplicated(), :] = 0
print (df2)
   123_PD  456_PD  789_PD
0     0.0     0.0     0.0
1     0.5     0.6     3.0
2    -1.5    -1.3     NaN
3    -2.4    -2.3     0.0
4     0.0     0.0     0.0
5     0.4     0.5     2.9
6     1.4     1.6     NaN

df = df.join(df2)
print (df)
  ID        Date  X  123_P  456_P  789_P  choice  123_PD  456_PD  789_PD
0  A  07/16/2019  .    1.5    1.8    1.6     123     0.0     0.0     0.0
1  A  07/17/2019  .    2.0    2.1    4.5     789     0.5     0.6     3.0
2  A  07/18/2019  .    3.0    3.2    NaN       0    -1.5    -1.3     NaN
3  A  07/19/2019  .    2.1    2.2    4.5     456    -2.4    -2.3     0.0
4  B  07/16/2019  .    1.5    1.8    1.6     789     0.0     0.0     0.0
5  B  07/17/2019  .    2.0    2.1    4.5       0     0.4     0.5     2.9
6  B  07/18/2019  .    3.0    3.2    NaN     123     1.4     1.6     NaN
0 голосов
/ 23 сентября 2019

Это должно сделать необходимое:

df[['123_PD', '456_PD', '789_PD']] = df[['123_P', '456_P', '789_P']] - df[['123_P', '456_P', '789_P']].shift(1) 

df['123_PD'].iloc[0] = 0
df['456_PD'].iloc[0] = 0
df['789_PD'].iloc[0] = 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...