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

У меня есть следующий кадр данных

id  Supply  days    days_180
1   30         0    180
1   100      183    363
1   80       250    430
2   5          0    180
2   5         10    190
3   5          0    180
3   30       100    280
3   30       150    330
3   30       200    380
3   30       280    460
3   50       310    490

Я хочу суммировать «Предложение», где дни находятся между «днями» и «днями + 180» для каждой строки. Это необходимо сделать для каждой группы после groupby ('id').

Ожидаемый вывод такой, как показано ниже

id  Supply  days    days_180    use
1   30         0        180     30
1   100      183        363     180
1   80       250        430     80
2   5          0        180     10
2   5         10        190     10
3   5          0        180     65
3   30       100        280     120
3   30       150        330     140
3   30       200        380     110
3   30       280        460     80
3   50       310        490     50

Я пробовал приведенный ниже код, но он не работает какпредназначен.

df_d['use']=df_d.groupby('id').apply(lambda x: x.loc[x['days'].between(x['days'],x['days_180']),'supply'].sum())

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Используйте списочное понимание для цикла каждого days_180 значений для групп, отфильтруйте с помощью sum и создайте новый столбец:

def f(x):
    a = [x.loc[(x['days'] <= d) & (x['days_180'] >= d),'Supply'].sum() for d in x['days_180']]
    x['use'] = a
    return x

Или решение с другой лямбда-выражением:

def f(x):
    x['use'] = x['days_180'].apply(lambda d: x.loc[(x['days'] <= d) & 
                                                   (x['days_180'] >= d), 'Supply'].sum())
    return x


df_d = df_d.groupby('id').apply(f)
print (df_d)
    id  Supply  days  days_180  use
0    1      30     0       180   30
1    1     100   183       363  180
2    1      80   250       430   80
3    2       5     0       180   10
4    2       5    10       190    5
5    3       5     0       180   65
6    3      30   100       280  120
7    3      30   150       330  140
8    3      30   200       380  110
9    3      30   280       460   80
10   3      50   310       490   50
0 голосов
/ 15 октября 2019

вы также можете сделать это с помощью трансляции numpy и np.where

df.groupby("id").apply(
    lambda g: g.assign(use=(np.where((g.days.values>=g.days.values[:, np.newaxis]) & 
        (g.days.values<=g.days_180.values[:, np.newaxis]), g.Supply, 0).sum(axis=1)))
).reset_index(drop=True)

также можно изменить Jezrael's, как показано ниже, чтобы использовать лямбду в сторону применения

df = df.groupby('id').apply(lambda x:
    x.assign(use=[x.loc[(x['days'] <= d) & (x['days_180'] >= d),'Supply'].sum() for d in x['days_180']])
)
print (df)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...