Ответ 1
Это можно сделать с помощью аналогичного синтаксиса с groupby()
и apply()
:
df['ratio'] = df.groupby(['a','b'], group_keys=False).apply(lambda g: g.c/(g.c * g.d).sum())
Итак, в R, когда у меня есть кадр данных, состоящий из 4 столбцов, назовите его df
и я хочу вычислить отношение по суммированному произведению группы, я могу это сделать так:
// generate data
df = data.frame(a=c(1,1,0,1,0),b=c(1,0,0,1,0),c=c(10,5,1,5,10),d=c(3,1,2,1,2));
| a b c d |
| 1 1 10 3 |
| 1 0 5 1 |
| 0 0 1 2 |
| 1 1 5 1 |
| 0 0 10 2 |
// compute sum product ratio
df = df%>% group_by(a,b) %>%
mutate(
ratio=c/sum(c*d)
);
| a b c d ratio |
| 1 1 10 3 0.286 |
| 1 1 5 1 0.143 |
| 1 0 5 1 1 |
| 0 0 1 2 0.045 |
| 0 0 10 2 0.454 |
Но в python мне нужно прибегнуть к циклам. Я знаю, что должен быть более элегантный способ, чем исходные петли на питоне, у кого есть идеи?
Это можно сделать с помощью аналогичного синтаксиса с groupby()
и apply()
:
df['ratio'] = df.groupby(['a','b'], group_keys=False).apply(lambda g: g.c/(g.c * g.d).sum())
В соответствии с этим потоком на pandas github мы можем использовать метод transform()
для воспроизведения комбинации dplyr::groupby()
и dplyr::mutate()
. Для этого примера это будет выглядеть следующим образом:
df = pd.DataFrame(
dict(
a=(1 , 1, 0, 1, 0 ),
b=(1 , 0, 0, 1, 0 ),
c=(10, 5, 1, 5, 10),
d=(3 , 1, 2, 1, 2 ),
)
).assign(
prod_c_d = lambda x: x['c'] * x['d'],
ratio = lambda x: x['c'] / (x.groupby(['a','b']).transform('sum')['prod_c_d'])
)
В этом примере используется цепочка метода панд. Подробнее о том, как использовать цепочку методов для репликации рабочих процессов dplyr
, см. в этом блоге.
Метод с использованием apply()
и groupby()
не работает для меня, потому что он, кажется, не адаптируется. Например, это не сработает, если мы удалим g.c/
из лямбда-выражения.
df['ratio'] = df.groupby(['a','b'], group_keys=False)\
.apply(lambda g: (g.c * g.d).sum() )