Как посчитать процентное соотношение для каждого объекта в pandas?
У меня есть огромный дата сет на миллион строк, в котором есть название товара (product_id) и номера заказов (order_id), в которых эти товары приобретаются. Также у меня есть столбец (reordered), который отвечает за то, перезаказывается ли этот товар (1) или нет (0). Мне нужно посчитать для каждого продукта как часто он перезаказывается (т.е. как я это понимаю поделить кол-во раз перезаказа на общее количество взаимодействий этого товара).
product_id reordered order_id \
0 35108 1 1773739
1 35108 1 421943
2 35108 1 1292727
3 35108 1 560282
4 35108 1 1329397
... ... ... ...
907001 38046 0 2122080
907002 5453 1 1059039
907003 29000 0 2913355
907004 4908 0 1003143
907005 17645 0 476860
product_name aisle_id \
0 Salted Butter 36
1 Salted Butter 36
2 Salted Butter 36
3 Salted Butter 36
4 Salted Butter 36
... ... ...
907001 Braunschweiger 106
907002 100% Juice, Organic, Pomegranate 98
907003 Enchilada Sauce Spices & Seasonings 104
907004 Smooth & Silky Head and Shoulders Smooth & Sil... 22
907005 Fruit Refreshers Grapefruit and Oranges in Pom... 4
department_id
0 16
1 16
2 16
3 16
4 16
... ...
907001 12
907002 7
907003 13
907004 11
907005 9
Написал следующую функцию, но работает она очень медленно: n - количество возвратов и невозвратов, ставлю 10 обычно, чтобы не использовались товары, которые очень редки в продаже
def percentReorder(n):
percent, index = [], []
productList = new_df["product_name"].unique().tolist()
for i in productList:
aux_df= new_df[new_df["product_name"] == i]
if len(aux_df) >= n:
ones = len(aux_df[aux_df['reordered']==1])
zeros = len(aux_df[aux_df['reordered']==0])
percent.append(ones/(zeros+ones))
index.append(i)
return percent, index
Как можно переписать иначе, чтобы выполнялось намного быстрее?
Ответы (1 шт):
Достаточно сгруппировать фрейм по "product_id" и взять среднее арифметическое по столбцу "reordered" в каждой группе.
Пример:
In [274]: df
Out[274]:
product_id reordered
0 35108 1
1 35108 1
2 35108 1
3 35108 1
4 35108 1
5 12345 0
6 12345 0
7 12345 1
In [275]: df.groupby("product_id")["reordered"].mean()
Out[275]:
product_id
12345 0.333333
35108 1.000000
Name: reordered, dtype: float64
если значение нужно получить в качестве нового столбца, скопировав значение для каждой строки, тогда можно использовать .transform():
In [278]: df["pct_reordered"] = df.groupby("product_id")["reordered"].transform("mean")
In [279]: df
Out[279]:
product_id reordered pct_reordered
0 35108 1 1.000000
1 35108 1 1.000000
2 35108 1 1.000000
3 35108 1 1.000000
4 35108 1 1.000000
5 12345 0 0.333333
6 12345 0 0.333333
7 12345 1 0.333333