2014-12-11 7 views
4

Я это DataFrame (это просто пример, а не реальные данные):Вычислить дельта от значений в dataframe

In [1]: import pandas as pd 
     my_data = [{'client_id' : '001', 'items' : '10', 'month' : 'Jan'}, 
        {'client_id' : '001', 'items' : '20', 'month' : 'Feb'}, 
        {'client_id' : '001', 'items' : '30', 'month' : 'Mar'}, 
        {'client_id' : '002', 'items' : '30', 'month' : 'Jan'}, 
        {'client_id' : '002', 'items' : '20', 'month' : 'Feb'}, 
        {'client_id' : '002', 'items' : '15', 'month' : 'Mar'}, 
        {'client_id' : '003', 'items' : '10', 'month' : 'Jan'}, 
        {'client_id' : '003', 'items' : '20', 'month' : 'Feb'}, 
        {'client_id' : '003', 'items' : '15', 'month' : 'Mar'}] 
     df = pd.DataFrame(my_data) 

In [2]: df 
Out [2]:  
      client_id month  items 
     0  001  Jan   10 
     1  001  Feb   20 
     2  001  Mar   30 
     3  002  Jan   30 
     4  002  Feb   20 
     5  002  Mar   15 
     6  003  Jan   10 
     7  003  Feb   20 
     8  003  Mar   15 

То, что я хочу, чтобы вычислить дельту закупаемых для каждой пары месяцев. То есть, например, клиент «001» купил еще 10 предметов в феврале (20), чем в январе (10). Клиент «002», купил -10 штук (20 февраля, 30 января). Окончательный DataFrame будет выглядеть так:

In [3]: delta_df 
Out [3]: 
      client_id delta_items_feb delta_items_mar 
     0   001    10    10 
     1   002    -10    -5 
     2   003    10    -5 

Любые мысли о том, как это сделать?

ответ

1

Вот один из способов, с помощью pivot_table к первой группе количества элементов клиентом и месяц:

(я первый бросил в items столбец целых чисел с df.items = df.items.astype(int))

>>> table = df.pivot_table(values='items', rows='client_id', cols='month') 
>>> table = table[['Jan', 'Feb', 'Mar']] 
>>> pd.DataFrame(np.diff(table.values), 
       columns=['delta_items_feb', 'delta_items_mar'], 
       index=table.index).reset_index() 

    client_id delta_items_feb delta_items_mar 
0  001    10    10 
1  002    -10    -5 
2  003    10    -5 

Примечание: в более новые версии pandas, используйте index/columns вместо rows/cols при создании сводной таблицы.

Это:

  • шарниров данные по клиенту и дате, чтобы показать количество элементов для каждого
  • убеждаются столбцы в таблице отсортированы надлежащим образом по месяцам
  • использует np.diff для вычисления разницы между последовательными месяцами и создает новый DataFrame с нужными названиями колонок
+0

Se ems, как мы нашли одно и то же решение (pivot + diff), но в другом порядке;;) – elyase

+0

Итак, мы сделали :-) Я думаю, что я изначально пробовал 'groupby', но не мог подумать, как лучше всего использовать его здесь, так что это приятно видеть ваше решение. –

-1
1) clietn_id to set. Set to list client_listand sorted ['001','002','003'] . 
2) month string to int Jan-1;Feb-2;Mar -3 and etc 
3) for client in client_listand: 
    For every client create new list 
    for line in you_date: 
     When ides of clients coincide, add to the list #filter by client_id 
    sorted result by month 
    in the loop from data of one client generate the lines of outgoing table. 
    delta_items_mar = item[n]-item[n-1] 
1

Престижность для очень четко сформулированного вопроса. Группа клиента и расчет дельты для каждой группы:

>>> df['deltas'] = df.groupby('client_id')\ 
        .apply(lambda x: x['items'].astype(int).diff()).values 

    client_id items month deltas 
0  001  10 Jan  NaN 
1  001  20 Feb  10 
2  001  30 Mar  10 
3  002  30 Jan  NaN 
4  002  20 Feb  -10 
5  002  15 Mar  -5 
6  003  10 Jan  NaN 
7  003  20 Feb  10 
8  003  15 Mar  -5 

Наконец принять его в форму вы хотите уронить колонки января:

>>> df.pivot(index='client_id', columns='month', values='deltas')\ 
     .drop('Jan', axis=1) 

month  Feb Mar 
client_id  
001   10 10 
002  -10 -5 
003   10 -5 
+0

Я получаю эту ошибку при выполнении «df ['deltas'] = df.groupby ('client_id'). Apply (lambda x: x ['items']. Astype (int) .diff()). Values": " ValueError: длина значений не соответствует длине индекса ". Невозможно понять, почему ... – Andres

+0

Сравните вывод 'df.groupby ('client_id'). Apply (lambda x: x ['items']. Astype (int) .diff()). Values' с вашим оригиналом 'df', чтобы узнать, что вызывает разницу. Он работает нормально с вашими данными образца на моих пандах 0.15.1. – elyase

+0

Я получаю массив 3x3 после запуска 'df.groupby ('client_id'). Apply (lambda x: x ['items']. Astype (int) .diff()). Values' с значениями diff. Может быть, поэтому я не могу назначить 'df ['deltas']' массиву? Моя версия pandas 0.14.1 – Andres

0

не фантазии, но вот то, что работает для меня

#change 'items' from string to int 
## use loc to avoid "slice" warning 
df.loc[:,"items"] = df["items"].map(int) 

# use pivot to make columns for each unique value in "month" column 
dfp = df.pivot('client_id','month','items') 

# calculate delta and put in a new column 
dfp["dJF"] = dfp.Feb - dfp.Jan 

month  Feb Jan Mar dJF 
client_id     
001  20 10 30 10 
002  20 30 15 -10 
003  20 10 15 10 
Смежные вопросы