2015-06-19 3 views
5

У меня есть data.table как:R data.table: подгруппа взвешенных проценты группы

library(data.table) 
widgets <- data.table(serial_no=1:100, 
         color=rep_len(c("red","green","blue","black"),length.out=100), 
         style=rep_len(c("round","pointy","flat"),length.out=100), 
         weight=rep_len(1:5,length.out=100)) 

Хотя я не уверен, что это самый data.table способ, я могу вычислить частоту подгруппы по группам, используя table и length в один шаг - например, чтобы ответить на вопрос «Какой процент красных виджетов круглый?»

редактировать: этот код не дает правильный ответ

# example A 
widgets[, list(style = unique(style), 
       style_pct_of_color_by_count = 
       as.numeric(table(style)/length(style))), by=color] 

# color style style_pct_of_color_by_count 
# 1: red round      0.32 
# 2: red pointy      0.32 
# 3: red flat      0.36 
# 4: green pointy      0.32 
# ... 

Но я не могу использовать этот подход, чтобы ответить на такие вопросы, как «По весу, какой процент красных штучках круглые?» Я могу только придумать двухступенчатый подход:

# example B 
widgets[,list(cs_weight=sum(weight)),by=list(color,style)][,list(style, style_pct_of_color_by_weight=cs_weight/sum(cs_weight)),by=color] 

# color style style_pct_of_color_by_weight 
# 1: red round     0.3466667 
# 2: red pointy     0.3466667 
# 3: red flat     0.3066667 
# 4: green pointy     0.3333333 
# ... 

Я ищу одностадийный подход к В, и А если улучшаемые, в объяснении, что углубляет свое понимание о data.table синтаксисе для каждого конкретного групповые операции. Обратите внимание, что этот вопрос отличается от Weighted sum of variables by groups with data.table, поскольку мой раздел включает подгруппы и избегает нескольких шагов. TYVM.

+0

Глядя на ответ от @Frank ниже я заметил, что моя попытка А не только неудобно, но неправильно - например, я проверил 'виджетов [, сумма (style == "round" & color == "red")/sum (color == "red")] # 0.36' – C8H10N4O2

ответ

7

Это почти один шаг:

# A 
widgets[,{ 
    totwt = .N 
    .SD[,.(frac=.N/totwt),by=style] 
},by=color] 
    # color style frac 
# 1: red round 0.36 
# 2: red pointy 0.32 
# 3: red flat 0.32 
# 4: green pointy 0.36 
# 5: green flat 0.32 
# 6: green round 0.32 
# 7: blue flat 0.36 
# 8: blue round 0.32 
# 9: blue pointy 0.32 
# 10: black round 0.36 
# 11: black pointy 0.32 
# 12: black flat 0.32 

# B 
widgets[,{ 
    totwt = sum(weight) 
    .SD[,.(frac=sum(weight)/totwt),by=style] 
},by=color] 
# color style  frac 
# 1: red round 0.3466667 
# 2: red pointy 0.3466667 
# 3: red flat 0.3066667 
# 4: green pointy 0.3333333 
# 5: green flat 0.3200000 
# 6: green round 0.3466667 
# 7: blue flat 0.3866667 
# 8: blue round 0.2933333 
# 9: blue pointy 0.3200000 
# 10: black round 0.3733333 
# 11: black pointy 0.3333333 
# 12: black flat 0.2933333 

Как это работает: Построить свой знаменатель для группы верхнего уровня (color) перед выходом на более тонкую группу (color с style) табулирования.


Альтернативы. Если style сек в пределах каждого повтора color и это только для целей отображения, попробовать table:

# A 
widgets[, 
    prop.table(table(color,style),1) 
] 
#  style 
# color flat pointy round 
# black 0.32 0.32 0.36 
# blue 0.36 0.32 0.32 
# green 0.32 0.36 0.32 
# red 0.32 0.32 0.36 

# B 
widgets[,rep(1L,sum(weight)),by=.(color,style)][, 
    prop.table(table(color,style),1) 
] 

#  style 
# color  flat pointy  round 
# black 0.2933333 0.3333333 0.3733333 
# blue 0.3866667 0.3200000 0.2933333 
# green 0.3200000 0.3333333 0.3466667 
# red 0.3066667 0.3466667 0.3466667 

Для B, это расширяет данные таким образом, что существует одно наблюдение за каждую единицу веса. С большими данными такое расширение было бы плохой идеей (так как это так много памяти). Кроме того, weight должен быть целым числом; в противном случае его сумма будет автоматически усечена до одного (например, попробуйте rep(1,2.5) # [1] 1 1).

+0

Это то, что я делаю, но мне было бы интересно найти лучший способ. – Frank

+1

Спасибо @Frank - мне понадобится время, чтобы получить точную нотацию и встроенные задания, но это отличный подход. – C8H10N4O2

+1

Ваша первая версия может быть переписана без переменной temp следующим образом: 'widgets [,. (Frac = .SD [, .N, by = style] $ N/.N), by = color]' – Arun

0

это может быть хорошей идеей использовать dplyr

df <- widgets %>% 
    group_by(color, style) %>% 
    summarise(count = n()) %>% 
    mutate(freq = count/sum(count)) 

df2 <- widgets %>% 
    group_by(color, style) %>% 
    summarise(count_w = sum(weight)) %>% 
    mutate(freq = count_w/sum(count_w)) 
+0

Спасибо @ drsh1 Я ценю, что 'dplyr' является интуитивным и полезным здесь. Мой вопрос, в частности, заключался в том, как использовать синтаксис 'data.table'. – C8H10N4O2

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