наносить на матрицы данных и индексы - PullRequest
7 голосов
/ 27 октября 2011

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

index <- matrix(c("A","A","B","B","B","B","A","A"),4,2)
x <- matrix(1:8,4,2)

for (i in 1:2) {
  tapply(x[,i], index[,i], sum)
}

В конце дня мне нужен следующий результат:

   1  2
A  3  15
B  7  11

Есть ли способ сделать это, используя матричные операции без цикла? Кроме того, реальные данные большие (например, 500 х 10000), поэтому они должны быть быстрыми.

Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 27 октября 2011

Вот несколько решений:

# 1
ag <- aggregate(c(x), data.frame(index = c(index), col = c(col(x))), sum)
xt <- xtabs(x ~., ag)

# 2
m <- mapply(rowsum, as.data.frame(x), as.data.frame(index))
dimnames(m) <- list(levels(factor(index)), 1:ncol(index))

Второй работает, только если в каждом столбце index есть хотя бы один из каждого уровня, а также требуется, чтобы было как минимум 2 уровня; однако, это быстрее.

1 голос
/ 27 октября 2011

Я все еще подозреваю, что есть лучший вариант, но на самом деле он кажется достаточно быстрым:

index <- matrix(sample(LETTERS[1:4],size = 500*1000,replace = TRUE),500,10000)
x <- matrix(sample(1:10,500*10000,replace = TRUE),500,10000)

rs <- matrix(NA,4,10000)
rownames(rs) <- LETTERS[1:4]
for (i in LETTERS[1:4]){
    tmp <- x
    tmp[index != i] <- 0
    rs[i,] <- colSums(tmp)
}

На моем компьютере он работает за ~ 0,8 секунды.Я увеличил количество категорий до четырех и увеличил их до размера данных, которые у вас есть.Но мне не нужно каждый раз копировать x.

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

1 голос
/ 27 октября 2011

Это уродливо и работает, но есть гораздо лучший способ сделать это более обобщенным.Просто шарик катится.

data.frame("col1"=as.numeric(table(rep(index[,1], x[,1]))),
           "col2"=as.numeric(table(rep(index[,2], x[,2]))), 
            row.names=names(table(index)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...