2016-04-17 2 views
2

Я пытаюсь выполнить задачу, которая концептуально проста, но мой код кажется слишком дорогим. Я ищу более быстрый способ, потенциально использующий встроенные функции pandas для объектов GroupBy.Python: эффективно применяйте объект pandas GroupBy

Отправной точкой является DataFrame, называемый ценами, с столбцами = [['item', 'store', 'day', 'price']], в котором каждое наблюдение является самым последним ценовым обновлением, специфичным для элемента -строчная комбинация. Проблема в том, что некоторые обновления цен совпадают с последним обновлением цены для одной и той же комбинации элементов. Например, давайте посмотрим на определенную части:

 day item_id store_id price 
35083 34 85376  211 5.95 
56157 41 85376  211 6.00 
63628 50 85376  211 5.95 
64955 51 85376  211 6.00 
66386 56 85376  211 6.00 
69477 69 85376  211 5.95 

В этом примере я хотел бы наблюдение, когда день равен 56 быть отброшен (потому что цена такой же, как последнее наблюдение в этой группе). Мой код:

def removeSameLast(df): 

    shp = df.shape[0] 
    lead = df['price'][1:shp] 
    lag = df['price'][:shp-1] 
    diff = np.array(lead != lag) 

    boo = np.array(1) 
    boo = np.append(boo,diff) 
    boo = boo.astype(bool) 

    df = df.loc[boo] 

    return df 

gCell = prices.groupby(['item_id', 'store_id']) 
prices = gCell.apply(removeSameLast) 

Это делает работу, но является уродливой и медленной. Извините за ноб, но я предполагаю, что это можно сделать гораздо быстрее. Может ли кто-нибудь предложить решение? Спасибо заранее.

ответ

1

Я предлагаю перейти к простому решению, используя функцию shift от Pandas. Это приведет к удалению использования groupby и вызова функции.

Идея состоит в том, чтобы увидеть, где серия [5.95, 6, 5.95, 6, 6, 5.95] равна сдвинутой, [nan, 5.95, 6, 5.95, 6, 6] и удалять (или просто не выбирать) строки, где это условие происходит.

>>> mask = ~np.isclose(prices['price'], prices['price'].shift()) 
>>> prices[mask] 
     day item_id store_id price 
35083 34 85376  211 5.95 
56157 41 85376  211 6.00 
63628 50 85376  211 5.95 
64955 51 85376  211 6.00 
69477 69 85376  211 5.95 

Простой тест:

%timeit prices = gCell.apply(removeSameLast) 
100 loops, best of 3: 4.46 ms per loop 

%timeit mask = df.price != df.price.shift() 
1000 loops, best of 3: 183 µs per loop 
+0

это плохая идея, чтобы сравнить двойной/плавать с помощью == или =, вместо этого, используйте np.isclose может быть лучше!. – PhilChang

+0

Спасибо за предложение Фила, я обновил создание маски с помощью 'mask = ~ np.isclose (цены ['price'], цены ['price']. Shift())' –

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