Python / Pandas: оптимизировать скорость unstack ('var'). Fillna (0) .stack ('var') - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть данные, содержащие информацию о идентификатор продукта как i, время предложения как t, идентификатор продавца как m и цена,Для каждого продукта i существует список времен t, по которому у меня есть цены для всех продавцов m.

Если у конкретного продавца m нет предложений по i на t, запись для (i,t,m) просто отсутствует.

Я бы хотел, чтобы запись с нулевой ценой сигнализировала, что этот продавец пока не предлагает.

Обратите внимание , что продавцы для каждого продукта являются отдельными: я хочу добавить записи для продавцов, которые появились в этом продукте в какой-то момент, а не для всех продавцов, которые появилисьна любом продукте в какой-то момент.

Следующий код достигает желаемого результата:

def addMissingMerchants(pDF):
    return pDF.set_index(['i','t','m']).unstack('m').fillna(0).stack('m').reset_index();

df = df.groupby('i').progress_apply(addMissingMerchants).drop('i',axis=1).reset_index().drop('level_1',axis=1);

Однако этот код работает довольно медленно: он обрабатывает около 15 продуктов в секунду в моей системе.

Можно ли как-нибудь быстрее добиться того же результата?

Минимальный рабочий пример:

          i                   t        m              p
40181    3996 2018-08-26 02:33:45      162082         67.90
40182    3996 2018-08-26 03:14:10      162082         67.90
40194    3996 2018-08-26 02:33:45      193879         58.00
40195    3996 2018-08-26 03:14:10      193879         58.00
40210    3996 2018-08-26 03:14:10      256684         57.98
40226    3996 2018-08-26 02:33:45      373084         58.00
40227    3996 2018-08-26 03:14:10      373084         58.00
40247    3996 2018-08-26 02:33:45     1238707         53.98
40248    3996 2018-08-26 03:14:10     1238707         53.98

Желаемый результат:

     i                      t      m              p
0    3996 2018-08-26 02:33:45      162082         67.90
1    3996 2018-08-26 02:33:45      193879         58.00
2    3996 2018-08-26 02:33:45      256684          0.00
3    3996 2018-08-26 02:33:45      373084         58.00
4    3996 2018-08-26 02:33:45     1238707         53.98
5    3996 2018-08-26 03:14:10      162082         67.90
6    3996 2018-08-26 03:14:10      193879         58.00
7    3996 2018-08-26 03:14:10      256684         57.98
8    3996 2018-08-26 03:14:10      373084         58.00
9    3996 2018-08-26 03:14:10     1238707         53.98

(обратите внимание на новую строку, начинающуюся с 2)

Текущее время:

%%timeit
addMissingMerchants(df)
100 loops, best of 3: 7.59 ms per loop

1 Ответ

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

Вместо того, чтобы восстанавливать и перекомпилировать, переиндексируйте весь фрейм данных.Сначала создайте список кортежей:

tuples = [];
for i, productData in df.groupby('i'):
    tList = productData.t.unique();
    for m in productData.m.unique():
        tuples.extend([(i,m,t) for t in tList]);

Затем используйте кортежи для переиндексации фрейма данных:

df = df.set_index(['i','m','t']) 
df = df[~df.index.duplicated(keep='first')] 
idx = pd.MultiIndex.from_tuples(tuples,names=['i','m','t'])
df = df.reindex(idx,fill_value=0).reset_index()

Это займет пару минут для выполнения для всего фрейма данных, намного лучше, чемрешение groupby-unstack-restck (которое заняло около 1,5 часов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...