В этом проблема. Существует матрица с N строк и столбцов С, а два фактора: ids
и group
, обе длины N. Например:Перестройте матрицу в R, используя два фактора:
m <- matrix(1:25, nrow= 5, byrow= T)
id <- factor(c("A", "A", "A", "B", "B"))
group <- factor(c("a", "b", "c", "a", "c"))
Не все комбинации факторов присутствуют, но каждая комбинация факторов присутствует только один раз. Задача состоит в том, чтобы преобразовать матрицу m
таким образом, чтобы она имела length(levels(id))
строк и length(levels(group)) * C
столбцов. Другими словами, создайте матрицу, где каждая переменная соответствует комбинации между исходным столбцом и всеми возможными уровнями фактора group
. Отсутствующие значения (для несуществующих комбинаций id и группы) заменяются NA. Вот требуемый выход из приведенного выше примера:
a.1 a.2 a.3 a.4 a.5 b.1 b.2 b.3 b.4 b.5 c.1 c.2 c.3 c.4 c.5
A 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
B 16 17 18 19 20 NA NA NA NA NA 21 22 23 24 25
я написал свою собственную функцию, но это очень неэффективно, и я уверен, что он дублирует функциональность что-то очень простое.
matrixReshuffle <- function(m, ids.row, factor.group) {
nr <- nrow(m)
nc <- ncol(m)
if(is.null(colnames(m))) colnames(m) <- 1:nc
ret <- NULL
for(id in levels(ids.row)) {
r <- c()
for(fg in levels(factor.group)) {
d <- m[ ids.row == id & factor.group == fg,, drop= F ]
if(nrow(d) > 1)
stop(sprintf("Too many matches for ids.row= %s and factor.group= %s", id, fg))
else if(nrow(d) < 1) {
r <- c(r, rep(NA, nc))
} else {
r <- c(r, d[1,])
}
}
ret <- rbind(ret, r)
}
colnames(ret) <- paste(rep(levels(factor.group), each= nc), rep(colnames(m), length(levels(factor.group))), sep= ".")
rownames(ret) <- levels(ids.row)
return(ret)
}
+1 Отличное решение; как я сказал в своем комментарии к собственному ответу, это то, что я бы предпочел. Вы можете рассмотреть 'acast', чтобы дать матрицу напрямую, и чтобы имена соответствовали, возможно, имена (df) <- 1: 5' перед таянием и' colnames (out) <- sub ("_", ". ", colnames (out))' после кастинга (где 'out' является результатом литья). – Aaron
@ Аарон, да, я должен был использовать 'acast'. Спасибо за это. Я хотел дать общую идею и оставить остальную часть редактирования OP. Но теперь, после вашего комментария, я отредактировал его, чтобы он был полным. – Arun
@ января, спасибо за редактирование. – Arun