Как отфильтровать объект группы Pandas по 1 значению и использовать его для вычисления нового столбца? - PullRequest
0 голосов
/ 03 сентября 2018

В настоящее время я работаю с DataFrame (df) следующим образом:

df = pd.DataFrame({'fc_group': ['A', 'A', 'A','B', 'B', 'B', 'B', 'A', 'A', 'B','B'], 
                    'dt': ['2015-05-08', '2015-05-08', '2015-05-08', '2015-05-08', 
                           '2015-05-08', '2015-05-08', '2015-05-08', '2015-05-09', 
                           '2015-05-09', '2015-05-09', '2015-05-09'], 
                    'day': [0,1,2,0,1,2,3,1,2,0,1],
                    'value' : [50,150,200,60,170,220,378,140,240,700,1700]})

   fc_group          dt  day  value
0         A  2015-05-08    0     50
1         A  2015-05-08    1    150
2         A  2015-05-08    2    200
3         B  2015-05-08    0     60
4         B  2015-05-08    1    170
5         B  2015-05-08    2    220
6         B  2015-05-08    3    378
7         A  2015-05-09    1    140
8         A  2015-05-09    2    240
9         B  2015-05-09    0    700
10        B  2015-05-09    1   1700

Я хочу сгруппировать это по "fc_group" и "dt" и создать новый столбец с именем "new_column", который рассчитывается по

df [значение] / df [df [день] == 0] [значение]

или

np.nan , если в группе нет строки дня 0.

Результат должен выглядеть следующим образом (я выделил получившиеся группы)

   fc_group          dt  day  value  new_column
0         A  2015-05-08    0     50        1.00
1         A  2015-05-08    1    150        3.00
2         A  2015-05-08    2    200        4.00

3         B  2015-05-08    0     60        1.00
4         B  2015-05-08    1    170        2.83
5         B  2015-05-08    2    220        3.67
6         B  2015-05-08    3    378        6.30

7         A  2015-05-09    1    140        NaN
8         A  2015-05-09    2    240        NaN

9         B  2015-05-09    0    700        1.00
10        B  2015-05-09    1   1700        2.43

Есть ли гладкий питонский способ достичь этого? Или пользовательская функция, вызываемая .apply или даже в лямбда-функции? Я пробовал несколько подходов, но ни один из них не работает (например, с лямбда-функциями, я не могу получить одно конкретное значение дня 0, с таможенными функциями и применяю, я получаю ошибки "несовместимый индекс")

Единственное рабочее решение, которое я нашел, - это создать объект groupby, затем вручную выполнить итерацию по каждой группе с помощью цикла for, выполнить создание столбца, а затем рекомбинировать все подгруппы. Это довольно медленно и кажется крайне неэффективным. Спасибо за помощь:)

1 Ответ

0 голосов
/ 03 сентября 2018

Только первый фильтр 0 значения по eq с boolean indexing, затем merge с левым соединением и делением на div:

new = df[df['day'].eq(0)].rename(columns={'value':'new'})
#if possible multiple `0` values per columns 'fc_group','dt' get first rows only
#new = df[df['day'].eq(0)].drop_duplicates(subset=['fc_group','dt']).rename(columns={'value':'new'})
df['new'] = df['value'].div(df.merge(new, how='left', on=['fc_group','dt'])['new'])
print (df)
   fc_group          dt  day  value       new
0         A  2015-05-08    0     50  1.000000
1         A  2015-05-08    1    150  3.000000
2         A  2015-05-08    2    200  4.000000
3         B  2015-05-08    0     60  1.000000
4         B  2015-05-08    1    170  2.833333
5         B  2015-05-08    2    220  3.666667
6         B  2015-05-08    3    378  6.300000
7         A  2015-05-09    1    140       NaN
8         A  2015-05-09    2    240       NaN
9         B  2015-05-09    0    700  1.000000
10        B  2015-05-09    1   1700  2.428571
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...