Получение значения из других строк в группе - PullRequest
0 голосов
/ 06 сентября 2018

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

df = pd.DataFrame([
    {'id': 1, 'bonus': True, 'value': 10 },
    {'id': 1, 'bonus': True, 'value': 15 },
    {'id': 1, 'bonus': False, 'value': 5 },

    {'id': 2, 'bonus': False, 'value': 20 },
    {'id': 2, 'bonus': True, 'value': 10 },
])

Я хочу добавить дополнительное значение «bonus_value» к каждому идентификатору, содержащее сумму всех связанных бонусов, если текущая строка не является бонусом.Что-то вроде:

    {'id': 1, 'bonus': True, value: 10, bonus_value: 0 },
    {'id': 1, 'bonus': True, value: 15, bonus_value: 0 },
    {'id': 1, 'bonus': False, value: 5, bonus_value: 25 },

    {'id': 2, 'bonus': False, value: 20, bonus_value: 10 },
    {'id': 2, 'bonus': True, value: 10, bonus_value: 0 },

Бонус не может быть привязан к бонусу.И я просто хочу получить сумму всех связанных с этим бонусов в свойстве bonus_value.

Я попытался сгруппировать их:

per_id_groups = df.groupby(["id", "bonus"]).sum().reset_index()

updated_df = df.merge(
    per_id_groups,
    on=["id", "bonus"],
    suffixes=["", "_with_bonus"]
)

updated_df["bonus_value"] = updated_df["value_with_bonus"] - updated_df["value"]

Но, очевидно, это не работает:

   bonus  id  value  value_with_bonus  bonus_value
0   True   1     10                25           15
1   True   1     15                25           10
2  False   1      5                 5            0
3  False   2     20                20            0
4   True   2     10                10            0

Действительно, у меня не должно быть никакого значения в столбце bonus_value, когда это бонус.И, что еще раздражает, у меня нет суммы в bonus=False строках.

Я не могу найти способ решить эту проблему.Я полагаю, мне следует пропустить функцию Панд здесь?:)

Ответы [ 3 ]

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

вариант 1

df.assign(
    bonus_value=df[~df.bonus].id.map(df.groupby(['bonus', 'id']).value.sum().xs(True)))

   bonus  id  value  bonus_value
0   True   1     10          NaN
1   True   1     15          NaN
2  False   1      5         25.0
3  False   2     20         10.0
4   True   2     10          NaN

вариант 2

Это я экспериментирую

d2 = df.groupby(['bonus', 'id']).value.sum().rename('bonus_value').reset_index()
d2.bonus_value *= d2.bonus
d2.bonus ^= True
df.merge(d2)

   bonus  id  value  bonus_value
0   True   1     10            0
1   True   1     15            0
2  False   1      5           25
3  False   2     20           10
4   True   2     10            0
0 голосов
/ 06 сентября 2018

Может фильтровать, используя df.bonus и index matching

df = df.set_index('id')
df.loc[~df.bonus,'bonus_value'] = df.loc[df.bonus].groupby('id').value.sum()
df.reset_index().fillna(0)

    id  bonus   value   bonus_value
0   1   True    10      0.0
1   1   True    15      0.0
2   1   False   5       25.0
3   2   False   20      10.0
4   2   True    10      0.0
0 голосов
/ 06 сентября 2018

Вы можете сделать с двумя шагами

df['bonus_value']=df.id.map(df[df.bonus].groupby('id').value.sum())# map the sum value for each group
df.loc[df.bonus,'bonus_value']=0 #then assign 0 to bonus is True
df
Out[205]: 
   bonus  id  value  bonus_value
0   True   1     10            0
1   True   1     15            0
2  False   1      5           25
3  False   2     20           10
4   True   2     10            0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...