2016-05-01 2 views
3

У меня есть файл csv с четырьмя столбцами: дата, оптовый продавец, продукт и продажи. Я ищу поиск средних продаж за последние 52 недели для каждой комбинации продуктов и оптовых продавцов на каждую дату. Это означает, что средние предыдущие продажи продукта «A» у оптового торговца «B» в момент «C» за последние 52 недели.Как найти среднее значение за последние 52 недели продаж за каждый раз в python

Например, мы знаем, что продажи продукта «A» у оптового торговца «B» в январе, апреле, мае, августе, которые составляют 100, 200, 300, 400 соответственно. Предположим, что у нас нет записей до января. Таким образом, среднее значение предыдущей продажи продукта «А» у оптового торговца «В» в апреле равно 100/1, а в мае равно (200 + 100)/2 и в августе - (300 + 200 + 100)/3.

В следующей таблице приведены мои данные:

date wholesaler product sales 
12/31/2012 53929 UPE54  4 
12/31/2012 13131 UPE55  1 
2/23/2013 13131 UPE55 1156 
4/24/2013 13131 UPE55  1 
12/1/2013 83389 UPE54  9 
12/17/2013 83389 UPE54  1 
12/18/2013 52237 UPE54  9 
12/19/2013 53929 UME24  1 
12/31/2013 82204 UPE55  9 
12/31/2013 11209 UME24  4 
12/31/2013 52237 UPE54  1 

Сейчас я использую:

df = pd.read_csv('Sample.csv',index_col='date') 

expd_gb = df.reset_index().groupby(['wholesaler', 'product'])['sales'].apply(pd.Series.expanding) 
idx = df.reset_index().groupby(['wholesaler', 'product', 'date'])['sales'].count().index 

cnct = pd.concat([expd_gb.iloc[n].mean().shift(1) for n in range(len(expd_gb))]) 
cnct.index = idx 

Это дает общее среднее (не последние 52 недели) предыдущих продаж для каждого продукта-Оптовик комбинации. В результате получилось:

wholesaler product date  
11209  UME24 12/31/2013  NaN 
13131  UPE55 12/31/2012  NaN 
        2/23/2013  1.0 
        4/24/2013  578.5 
52237  UPE54 12/18/2013  NaN 
        12/31/2013  9.0 
53929  UME24 12/19/2013  NaN 
      UPE54 12/31/2012  NaN 
82204  UPE55 12/31/2013  NaN 
83389  UPE54 12/1/2013  NaN 
        12/17/2013  9.0 

Со временем итерация записи о продажах увеличивается. Мне нужно выяснить, что среднее из продаж только за последние 52 недели. Это означает, что в определенную дату, например, 11/6/2015, какова средняя продажа продукта у определенного оптовика за последние 52 недели. Спасибо миллион за вашу помощь!

ответ

2

Рассмотрите функцию apply, условно усредняющую последние 52 недели продаж оптовиком и продуктом для каждой записи. Без обходного пути groupby() возвращает одно и то же значение для группы, тогда как вам нужен тип бегущей группы, поэтому попробуйте выполнить обработку по серии. И обязательно конвертируйте дату в формат datetime, так как вы можете использовать timedelta(), чтобы пересчитать 52 недели.

import pandas as pd 
import datetime 

dateparse = lambda x: pd.datetime.strptime(x, '%m/%d/%Y') 

df = pd.read_csv('Sample.csv', index_col='date', 
       parse_dates=[0], date_parser=dateparse) 

def last52weeks(x): 
    ser = df['sales'][(df.index >= x.name - datetime.timedelta(weeks=52)) & 
         (df.index <= x.name) & 
         (df['wholesaler'] == x[0]) & 
         (df['product'] == x[1])] 
    return ser.mean() 

df['avg_sales_last52weeks'] = df.apply(last52weeks, axis=1) 
df = df.sort_values(['wholesaler', 'product']) 

#    wholesaler product sales avg_sales_last52weeks 
# date               
# 2013-12-31  11209 UME24  4      4.0 
# 2012-12-31  13131 UPE55  1      1.0 
# 2013-02-23  13131 UPE55 1156     578.5 
# 2013-04-24  13131 UPE55  1     386.0 
# 2013-12-18  52237 UPE54  9      9.0 
# 2013-12-31  52237 UPE54  1      5.0 
# 2013-12-19  53929 UME24  1      1.0 
# 2012-12-31  53929 UPE54  4      4.0 
# 2013-12-31  82204 UPE55  9      9.0 
# 2013-12-01  83389 UPE54  9      9.0 
# 2013-12-17  83389 UPE54  1      5.0 
+0

Большое спасибо! Это потрясающе!Считаете ли вы, что функция timedelta() 'может работать быстрее? На самом деле мне нужно вычислить более 25 миллионов строк, и я надеюсь найти быстрый способ найти результат. Еще раз спасибо за ваш элегантный код! – Ashkan

+1

Ничего себе! Достаточно набор данных. Рассмотрим SQL-решение базы данных, используя условные агрегированные запросы для запуска avg и индексной таблицы на дату. Затем импортируйте в pandas df. – Parfait

+0

Большое спасибо за ваш комментарий! Это хорошая идея. – Ashkan

1

Если среднее значение среднего значения в неделю, вы не должны делить сумму (за продукт на оптовика) на количество недель, то есть 52, вместо того, чтобы получать среднее значение в cnct = pd.concat ([expd_gb. iloc [n] .mean(). shift (1) для n в диапазоне (len (expd_gb))])?

Если у вас меньше 52 недель, вы хотите разделить общий объем продаж этого продукта на этого оптовика на количество недель, которое у вас есть. Например, если в январе (2016 г.) вы продали 100 виджетах, 200 в феврале и 400 в марте, то общий объем продаж по состоянию на 1 апреля составил бы 700. В январе, 29 в феврале и 31 марта, 31 января, так общее количество дней составляет 91, что составляет 13 недель (91/7). Таким образом, средний недельный объем продаж за этот трехмесячный период составит 700/13 или приблизительно. 53.85 виджетов в неделю. Неважно, было ли у вас 91 ежедневная запись, 13 еженедельных записей или 3 ежемесячных отчета, среднее значение в неделю по-прежнему остается неизменным.

Чтобы получить количество дней (и от них недель), вы можете посмотреть объекты timedelta. Как только вы займете более 52 недель, вы также можете использовать timedelta для определения того, что дата была 52 недели (или 364 дня) назад, и когда вы читаете файл, отмените что-либо до этой даты.

+0

Спасибо за ваш комментарий! Это немного сложнее. В первый год с тех пор, как у нас меньше 52 записей за продукт на оптовика, мы можем использовать среднее количество всех записей, но в следующие годы мы просто ищем среднее значение за последние 52 недели. Также вся комбинация продуктов и оптовых продавцов не имеет недельных записей, что означает для определенного продукта-оптовика, например, у нас есть 12 записей, поэтому среднее значение должно быть суммой (12 записей)/52. На самом деле, я думаю, что ваш комментарий верен, но я не знаю, как помешать логике! – Ashkan

Смежные вопросы