Создание кадра данных из матрицы в R
Как получить кадр данных с теми же данными, что и уже существующая матрица?
Упрощенный пример моей матрицы:
mat <- matrix(c(0, 0.5, 1, 0.1, 0.2, 0.3, 0.3, 0.4, 0.5),
ncol=3, nrow=3,
dimnames=list(NULL, c("time", "C_0", "C_1")))
> mat
time C_0 C_1
[1,] 0.0 0.1 0.3
[2,] 0.5 0.2 0.4
[3,] 1.0 0.3 0.5
Я хотел бы создать фрейм данных, который выглядит так:
name time val
1 C_0 0.0 0.1
2 C_0 0.5 0.2
3 C_0 1.0 0.3
4 C_1 0.0 0.3
5 C_1 0.5 0.4
6 C_1 1.0 0.5
Все мои попытки довольно неуклюжи, например:
data.frame(cbind(c(rep("C_1", 3), rep("C_2", 3)),
rbind(cbind(mat[,"time"], mat[,"C_0"]),
cbind(mat[,"time"], mat[,"C_1"]))))
Есть ли у кого-нибудь идеи, как сделать это более элегантно? Обратите внимание: мои реальные данные содержат еще несколько столбцов (40 столбцов).
Ответы
Ответ 1
Если вы измените столбец time
на имена строк, вы можете использовать as.data.frame(as.table(mat))
для простых случаев, подобных этому.
Пример:
> data <- c(0.1, 0.2, 0.3, 0.3, 0.4, 0.5)
> dimnames <- list(time=c(0, 0.5, 1), name=c("C_0", "C_1"))
> mat <- matrix(data, ncol=2, nrow=3, dimnames=dimnames)
> as.data.frame(as.table(mat))
time name Freq
1 0 C_0 0.1
2 0.5 C_0 0.2
3 1 C_0 0.3
4 0 C_1 0.3
5 0.5 C_1 0.4
6 1 C_1 0.5
В этом случае время и имя - оба фактора. Вы можете преобразовать время обратно в числовое, или это может не иметь значения.
Ответ 2
Вы можете использовать stack
из базового пакета. Но сначала вам нужно заставить матрицу привязать к data.frame
и изменить порядок столбцов после того, как данные будут сложены.
mat <- as.data.frame(mat)
res <- data.frame(time= mat$time,stack(mat,select=-time))
res[,c(3,1,2)]
ind time values
1 C_0 0.0 0.1
2 C_0 0.5 0.2
3 C_0 1.0 0.3
4 C_1 0.0 0.3
5 C_1 0.5 0.4
6 C_1 1.0 0.5
Обратите внимание, что stack
обычно более эффективен, чем пакет reshape2
.
Ответ 3
melt()
из пакета reshape2 позволяет вам закрыть...
library(reshape2)
(res <- melt(as.data.frame(mat), id="time"))
# time variable value
# 1 0.0 C_0 0.1
# 2 0.5 C_0 0.2
# 3 1.0 C_0 0.3
# 4 0.0 C_1 0.3
# 5 0.5 C_1 0.4
# 6 1.0 C_1 0.5
... хотя вы можете постовать свои результаты, чтобы получить ваши предпочтительные имена столбцов и порядок.
setNames(res[c("variable", "time", "value")], c("name", "time", "val"))
# name time val
# 1 C_0 0.0 0.1
# 2 C_0 0.5 0.2
# 3 C_0 1.0 0.3
# 4 C_1 0.0 0.3
# 5 C_1 0.5 0.4
# 6 C_1 1.0 0.5
Ответ 4
Я обнаружил, что следующий "чит" работает очень аккуратно и без ошибок
> dimnames <- list(time=c(0, 0.5, 1), name=c("C_0", "C_1"))
> mat <- matrix(data, ncol=2, nrow=3, dimnames=dimnames)
> head(mat, 2) #this returns the number of rows indicated in a data frame format
> df <- data.frame(head(mat, 2)) #"data.frame" might not be necessary
Et voila!