2013-07-08 4 views
1

Это то, что выглядит мои данные заказа клиента, как для одного клиента:Использование R data.table агрегировать выбора строк

order_no customer_id product amount order_total 
     23   1  A 100   100 
     24   1  A 100   300 
     24   1  B 100   300 
     24   1  C 100   300 
     25   1  B 100   100 
     26   1  A 100   200 
     26   1  B 100   200 

Я хочу, чтобы рассчитать средний размер заказа для каждого клиента в новый столбец, так для этого клиента было бы = 175 (100 + 300 + 100 + 200)/4:

order_no customer_id amount order_total avg_order_size 
     23   1  100   100    175 
     24   1  100   300    175 
     24   1  100   300    175 
     24   1  100   300    175 
     25   1  100   100    175 
     26   1  100   200    175 
     26   1  100   200    175 

Я пытался использовать какую-то версию, но не повезло:

customer_stats <- data.table(customer_stats)[, avg_order_size := mean(order_total), by=list(order_no, customer_id)] 

Что мне действительно нужно сделать, это выбрать только одну строку из каждого order_no, что-то вроде mean из всех order_no[1], используя by=(customer_id) возможно? Если есть способ сделать это одним шагом и пропустить создание order_total, тогда это еще лучше.

+0

ли вы попробовать 'customer_stats [, avg_order_size: = среднее (order_total), по списку = (order_no, customer_id)]' с помощью ': =' уже выполняет задание поэтому нет необходимости дополнительные не назначить 'данных. table' – dickoa

+0

@ dickoa, если вы группируете как 'order_no', так и' customer_id', тогда вы будете использовать «100, 300, 100, 200' * отдельно * (которые будут иметь те же значения). – Arun

+0

@Arun Да, вы правы – dickoa

ответ

0

Вы можете избежать создания order_total, делая это:

customer_stats[ , avg_order_size := sum(amount, na.rm=TRUE)/length(unique(order_no)), by=customer_id] 

Однако, у меня есть сомнения относительно того, как быстро это будет.

+0

Извините, но почему вы суммируете 'amount' здесь? Он суммирует '100 + 300 + 100 + 200' (который находится в' order_total', а не 'amount')? – Arun

+0

Багетный эффект! Он создал 'order_total' суммирование' amount' на 'order_no'. См. Редактирование его вопроса, где он спрашивает, можно ли это сделать без вычисления 'order_total'. – asb

+0

Ага, я вижу это сейчас. – Arun

2

Как насчет этого, он, кажется, переводит ваш подход и не требует вычисления order_total здесь.

dat[, sum(amount), by = list(customer_id, order_no)][ ,avg_order := mean(V1), by = customer_id] 
0

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

# Your data (next time, consider putting R-formatted data in the question...): 
dt <- data.table(customer_id=1, 
       order_no=c(23,24,24,24,25,26,26), 
       product=c("A","A","B","C","B","A","B"), 
       product_amount=100, 
       key=c("customer_id","order_no")) # 1: key by customer and order 

dt 
# customer_id order_no product product_amount 
#1:   1  23  A   100 
#2:   1  24  A   100 
#3:   1  24  B   100 
#4:   1  24  C   100 
#5:   1  25  B   100 
#6:   1  26  A   100 
#7:   1  26  B   100 

dt[ # 4: join summary back to original 
    dt[,list(order_total=sum(product_amount)),by=list(customer_id,order_no)] [ # 2: order total by customer and order 
    ,avg_order_size:=mean(order_total),by=list(customer_id)] # 3: add the average of order total by customer 
    ] 
# customer_id order_no product product_amount order_total avg_order_size 
#1:   1  23  A   100   100   175 
#2:   1  24  A   100   300   175 
#3:   1  24  B   100   300   175 
#4:   1  24  C   100   300   175 
#5:   1  25  B   100   100   175 
#6:   1  26  A   100   200   175 
#7:   1  26  B   100   200   175 
Смежные вопросы