2013-08-20 2 views
1

У меня есть следующий кадр данных в R:R - рассчитывать показатели по нескольким колонкам (например, SUMPRODUCT в Excel)

df <- data.frame(id=c('a','b','a','c','b','a'), 
       indicator1=c(1,0,0,0,1,1), 
       indicator2=c(0,0,0,1,0,1), 
       extra1=c(4,5,12,4,3,7), 
       extra2=c('z','z','x','y','x','x')) 

id indicator1 indicator2 extra1 extra2 
a   1   0  4  z 
b   0   0  5  z 
a   0   0  12  x 
c   0   1  4  y 
b   1   0  3  x 
a   1   1  7  x 

Я хотел бы добавить новый столбец с отсчетом по всем строкам числа что конкретный идентификатор имеет различные индикаторы, равные 1. Например:

id indicator1 indicator2 extra1 extra2 countInd1 countInd2 countInd1Ind2 
a   1   0  4  z  2   1   1 
b   0   0  5  z  1   0   0 
a   0   0  12  x  2   1   1 
c   0   1  4  y  0   1   0 
b   1   0  3  x  1   0   0 
a   1   1  7  x  2   1   1 

Как это сделать?

ответ

4

Существует несколько способов. Вот один с ave и within:

within(df, { 
    ind1ind2 <- ave(as.character(interaction(indicator1, indicator2, drop=TRUE)), 
        id, FUN = function(x) sum(x == "1.1")) 
    ind2 <- ave(indicator2, id, FUN = function(x) sum(x == 1)) 
    ind1 <- ave(indicator1, id, FUN = function(x) sum(x == 1)) 
}) 
# id indicator1 indicator2 extra1 extra2 ind1 ind2 ind1ind2 
# 1 a   1   0  4  z 2 1  1 
# 2 b   0   0  5  z 1 0  0 
# 3 a   0   0  12  x 2 1  1 
# 4 c   0   1  4  y 0 1  0 
# 5 b   1   0  3  x 1 0  0 
# 6 a   1   1  7  x 2 1  1 

Вот альтернатива:

A <- setNames(aggregate(cbind(indicator1, indicator2) ~ id, df, 
         function(x) sum(x == 1)), c("id", "ind1", "ind2")) 
B <- setNames(aggregate(interaction(indicator1, indicator2, drop = TRUE) ~ id, 
         df, function(x) sum(x == "1.1")), c("id", "ind1ind2")) 
Reduce(function(x, y) merge(x, y), list(df, A, B)) 
# id indicator1 indicator2 extra1 extra2 ind1 ind2 ind1ind2 
# 1 a   1   0  4  z 2 1  1 
# 2 a   0   0  12  x 2 1  1 
# 3 a   1   1  7  x 2 1  1 
# 4 b   0   0  5  z 1 0  0 
# 5 b   1   0  3  x 1 0  0 
# 6 c   0   1  4  y 0 1  0 

Конечно, если ваши данные большие, вы хотите, чтобы исследовать "data.table" пакет. Это также немного меньше, чем версия within.

library(data.table) 
DT <- data.table(df) 
DT[, c("ind1", "ind2", "ind1ind2") := 
    list(sum(indicator1 == 1), 
      sum(indicator2 == 1), 
      sum(interaction(indicator1, indicator2, 
          drop = TRUE) == "1.1")), 
    by = "id"] 
DT 
# id indicator1 indicator2 extra1 extra2 ind1 ind2 ind1ind2 
# 1: a   1   0  4  z 2 1  1 
# 2: b   0   0  5  z 1 0  0 
# 3: a   0   0  12  x 2 1  1 
# 4: c   0   1  4  y 0 1  0 
# 5: b   1   0  3  x 1 0  0 
# 6: a   1   1  7  x 2 1  1 

И, вместо того, чтобы sum(interaction(...) == "1.1"), вы можете также сделать sum(indicator1 == 1 & indicator2 == 1), если вы чувствуете, что это более явным. Я не тестировал, что лучше. interaction - это то, что мне впервые пришло в голову.

+0

если '' indicator1' и indicator2' являются (по мере их появления, и по всей видимости, будет называться) индикаторы, 'DT [ , c ('ind1', 'ind2', 'ind1ind2'): = list (сумма (индикатор1), сумма (индикатор2), сумма ((индикатор1 + индикатор2)> 1)), by = id] 'должны работать (и быть слабее более эффективным) – mnel

+0

@mnel, который произошел со мной, но я действительно не хотел делать никаких предположений о том, могут ли быть другие значения в столбцах «indicator1» и «indicator2». – A5C1D2H2I1M1N2O1R2T1

0

Или вы могли бы сделать это:

get_freq1 = function(i) {sum(df[which(df$id == df[i,1]),]$indicator1)} 
get_freq2 = function(i) {sum(df[which(df$id == df[i,1]),]$indicator2)} 

df = data.frame(df, countInd1 = sapply(1:nrow(df), get_freq1), countInd2 = sapply(1:nrow(df), get_freq2)) 
df= data.frame(df, countInd1Ind2 = ((df$countInd1 != 0) & (df$countInd2 != 0))*1) 

Вы получаете:

# id indicator1 indicator2 extra1 extra2 countInd1 countInd2 countInd1Ind2 
#1 a   1   0  4  z   2   1    1 
#2 b   0   0  5  z   1   0    0 
#3 a   0   0  12  x   2   1    1 
#4 c   0   1  4  y   0   1    0 
#5 b   1   0  3  x   1   0    0 
#6 a   1   1  7  x   2   1    1 
+0

Хотя я думаю, что код Ананды Махто довольно аккуратный! – Mayou

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