2016-10-20 17 views
1

Это связано с этим вопросом, который я просмотрел How to summarize by group?, однако, похоже, что мои данные немного отличаются друг от друга, что делает вещи странными. У меня есть data.frame DF как так:R: сумма путем подсчета по нескольким столбцам

X Y1 Y2 Y3 Y4 
3 A A B A 
2 B B A A 
1 B A A A 

Я хочу сделать что-то вроде взвешенной суммы каждого уникального фактора Y его числового значения в X, так что выход есть:

Y Y1 Y2 Y3 Y4 
A 3 4 3 6 
B 3 2 3 0 

Я попытался использовать цикл for для итерации по индексам столбцов, но я не смог правильно передать число Y, и это не похоже на R-способ сделать это эффективно, для еще много столбцов и строк.

Похоже, что в соответствии с связанным вопросом это правильный подход, однако, когда я пытаюсь расширить, чтобы сделать то же самое во всех столбцах, через group_by и summaryise, я получаю ошибки, так как факторы Y являются факторами. Должен ли я использовать «применить» вместо этого? Логика этого кажется прямой, но я был в тупике в ее реализации.

aggregate(X~Y1,DF,sum) 

ответ

4

Я не думаю, что это прямолинейно и потребует плавления и перестройки. Вот попытка в data.table:

setDT(df)  
dcast(melt(df, id.vars="X", value.name="Y")[,.(X=sum(X)), by=.(variable,Y)], Y ~ variable) 
#Using 'X' as value column. Use 'value.var' to override 
# Y Y1 Y2 Y3 Y4 
#1: A 3 4 3 6 
#2: B 3 2 3 NA 

Или, может быть, даже просто использовать xtabs, если вы хотите, чтобы избежать большей части data.table кода:

xtabs(X ~ Y + variable, melt(df, id.vars="X", value.name="Y")) 

Или вариации с использованием только базового R:

xtabs(X ~ ., cbind(df[1], stack(lapply(df[-1],as.character)))) 
0

Я не мог заставить выше работать, используя пакет data.table, поэтому я просто написал для себя свою функцию.

#@param x = vector of strings that we want to identify 
#@param DF = data frame, with the first column as weights and the rest containing strings 

#@return a matrix with the same cols and rows as identifiers. contains the summed weights 

return_reshape = function(x , DF) { 
    store_mat = matrix(0.0,length(x),ncol(DF) - 1) 
    dimnames(store_mat) = list(x,colnames(DF)[-1]) 
    for (row in 1:nrow(DF)) { 
     for (index in 1:length(x)) { 
      col_index = DF[row,-1] == x[index ] 
      store_mat[index ,col_index] = store_mat[index ,col_index] + as.numeric(DF[row,1]) 
    } 
} 
store_mat 
} 

DF = data.frame(X=3:1, Y1 = c("A","B","B"),Y2 = c("A","B","A"),Y3 = c("B","A","A"),Y4 = c("A","A","A"),stringsAsFactors=FALSE) 
x = as.character(c("A", "B")) 
return_reshape(x,DF) 
    Y1 Y2 Y3 Y4 
A 3 4 3 6 
B 3 2 3 0 
+0

Я не видел 'xtabs' решение по @thelatemail, которое приятно –

+0

Постарайся сделать' 'df' с data.table' объект первой через' setDT (DF) '- Я только что протестировал код снова, и он работает нормально. – thelatemail

0

Это на самом деле одна матрица %*% другая матрица.

X = matrix(c(3,2,1), nrow = 1) 
X 
    [,1] [,2] [,3] 
[1,] 3 2 1 

Y_A = matrix(c(1,1,0,1,0,0,1,1,0,1,1,1), nrow = 3, byrow = T) 
Y_A 

    [,1] [,2] [,3] [,4] 
[1,] 1 1 0 1 
[2,] 0 0 1 1 
[3,] 0 1 1 1 

Y_B = 1- Y_A 
Y_B 

    [,1] [,2] [,3] [,4] 
[1,] 0 0 1 0 
[2,] 1 1 0 0 
[3,] 1 0 0 0 

X %*% Y_A 
    [,1] [,2] [,3] [,4] 
[1,] 3 4 3 6 

X %*% Y_B 
    [,1] [,2] [,3] [,4] 
[1,] 3 2 3 0 

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

  • Нет связанных вопросов^_^