2012-05-25 2 views
2

В соответствии с Row wise matrix operations in R Я хотел бы применить функцию row-wise на таблице данных. Я хочу рассчитать в строке число средних столбцов в этой строке. Моя текущая попытка:Обратитесь к столбцам по номеру в: = присваивании при использовании data.table

columns <- c(1,5,10,15,20) # Actually obtained via grep 
my.data.table[,"average" := mean(columns),with=FALSE] # Or... 
my.data.table[,average := mean(columns)] 

Это, к сожалению, просто возвращает среднее значение вектора «столбцов», а не среднее значение столбцов, к которым они относятся. Есть ли способ ссылаться на эти столбцы по числу?

Вот среднем я пытаюсь достичь:

key a b c average 
A 5 5 5 5 
B 1 2 3 2 
C 2 4 9 5 
+0

Нет проблем, я ценю усилия! Посмотрим, сможет ли кто-нибудь найти решение. – Ina

ответ

3

Вот два возможных решения. Они в основном как из ссылки, которую вы уже предоставили, так что, возможно, я пропустил что-то с этим вопросом. Здесь мы идем:

Решение 1 (с помощью rowMeans):

library(data.table) 
N <- 1000000 
my.data.table <- data.table(ID = 1:N, 
          Year1 = rnorm(N), 
          Year2 = rnorm(N), 
          Year3 = rnorm(N), 
          Year4 = rnorm(N)) 

x <- c(2, 3, 4, 5) 
system.time(x1 <- rowMeans(my.data.table[, x, with=FALSE])) 
    user system elapsed 
    0.08 0.00 0.08 

Решение 2: Получить его в длинный формат первого. Я думал, что это было быстрее, главным образом из-за комментария Мэтью в другом вопросе, в котором говорится, что data.table предназначен для синтаксиса DT[,mad(variable),by=group]. Я думаю, что я что-то не хватает, но не понимаю, что:

library(reshape2) 
DT <- as.data.table(melt(as.data.frame(my.data.table), id.var="ID")) 
setkey(DT, ID) 
system.time(x2 <- DT[, mean(value), by="ID"][[2]]) 
    user system elapsed 
    11.28 0.00 11.33 
all.equal(x1, x2) 
[1] TRUE 
+1

+1 Я не могу бить 0.08. В этом случае нет никакой группировки. Группировка, где каждая строка является группой, действительно не группируется. Я согласился, что 'rowMeans' был лучшим (afaik) в комментариях в этом [другом вопросе] (http://stackoverflow.com/questions/9564588/row-wise-matrix-operations-in-r), а также упоминался« голый -bones ".colSums()', '.rowSums()', '.colMeans()' и '.rowMeans()', где требуется максимальная скорость, добавленная в R 2.15.0. –

+0

Хорошо, хорошо знать. Я ничего здесь не пропустил. Спасибо за разъяснения. –

+2

@MatthewDowle и Christoph_J - Похоже, я нашел что-то, что в 3-5 раз быстрее. Будет интересно, если у вас есть представление о том, почему это происходит намного быстрее. –

1

ОК еще один шанс ...

это было бы нормально

x<-1:5 
y<-1:5 
z<-1:5 
xy<-data.table(x,y,z) 
id<-c("x","y") 
newxy<-rowMeans(xy[, id, with=FALSE]) 
+0

Этот синтаксис не будет работать с data.table и colMeans здесь не применим. – Ina

+1

избили по времени .... alas –

+2

Только проблема с редактированием в том, что комментарии теперь не совпадают. Итак, просто для того, чтобы уточнить, 'rowMeans' отлично работает с' data.table', комментарий Ina был о первоначальном ответе, который сделал что-то еще. –

4

Другой альтернативой является построение вызова вы действительно хотите выполнить, а затем eval() его в DT[]. Это стратегия, описанная в разделах 1.5 и 1.6 данных. Таблица часто задаваемых вопросов (см. Ввод vignette("datatable-faq")).

Этот подход работает в 3-5 раз быстрее, чем при использовании rowMeans(). (Расхождение связано с rowMeans() 'начальное трудоемкая преобразование data.frames для матриц, так как Мэтью Dowle указывает в комментариях ниже.)

## Prepare data 
library(data.table) 
N <- 1000000 
DT <- data.table(ID = 1:N, 
       Year1 = rnorm(N), 
       Year2 = rnorm(N), 
       Year3 = rnorm(N), 
       Year4 = rnorm(N))  
x <- c(2, 3, 4, 5) 

## Construct the desired expression: (Year1 + Year2 + Year3 + Year4)/4 
addCols <- paste(names(DT)[x], collapse = " + ") 
e <- paste("(", addCols, ")/", length(x), sep="") 
e <- parse(text=e)[[1]] 

## Compare timings 
system.time(x2 <- DT[,eval(e)]) 
# user system elapsed 
# 0.11 0.00 0.11 
system.time(x1 <- rowMeans(DT[, x, with=FALSE])) 
# user system elapsed 
# 0.53 0.14 0.77 

## Check results 
# all.equal(x1,x2) 
# [1] TRUE 
+2

+10 Ницца! См. Первую строку 'rowMeans':' if (is.data.frame (x)) x = as.matrix (x) '. Так что сначала копирование в структуру «matrix». Это совпадает с тем, что между 'user' и' elapsed' для 'rowMeans' существует разница, которую вы избегаете с помощью прямого' eval'. Mult 'N' на' 10', а затем '10' снова, и разница должна расширяться. –

+0

@MatthewDowle - Да, вот и все.Спасибо за отслеживание этого! –

+0

NP. Не могли бы вы просмотреть [мой ответ] (http://stackoverflow.com/questions/1296646/how-to-sort-a-dataframe-by-columns-in-r) на самый верхний проголосовавший вопрос 'data.frame', и дать ему начало 0, если все в порядке? –

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