假设我有这个数据集,
library(data.table)
mydata <- data.table(col1=c(11,21,31),
col2=c(12,22,32),
col3=c(13,23,33))
mydata
col1 col2 col3
1: 11 12 13
2: 21 22 23
3: 31 32 33
我需要的是:
我有1,135行。愚蠢的解决方案是手动执行此操作。例如,
mynewdata=t(data.frame(mydata[1,],mydata[2,],mydata[3,]))
mynewdata
[,1]
col1 11
col2 12
col3 13
col1.1 21
col2.1 22
col3.1 23
col1.2 31
col2.2 32
col3.2 33
直到,我到了第1,135行。我知道它必须涉及某种循环?但我不知道如何循环。提前谢谢。
答案 0 :(得分:3)
基本上是一个带有行ID的melt
操作。尝试:
out <- setkey(melt(mydata[,row := .I], id.vars="row"),row)
out
# row variable value
#1: 1 col1 11
#2: 1 col2 12
#3: 1 col3 13
#4: 2 col1 21
#5: 2 col2 22
#6: 2 col3 23
#7: 3 col1 31
#8: 3 col2 32
#9: 3 col3 33
在基地R中,这是一个stack
:
out <- cbind(row=seq_len(nrow(mydata)),stack(mydata))
out[order(out$row),]
# row values ind
#1 1 11 col1
#4 1 12 col2
#7 1 13 col3
#2 2 21 col1
#5 2 22 col2
#8 2 23 col3
#3 3 31 col1
#6 3 32 col2
#9 3 33 col3
答案 1 :(得分:2)
我需要的是:
- 选择第一行并移调它。
- 然后,选择第二行并将其堆叠在第一行下。
- 然后,选择第三行和将其堆叠在第二行......等等。
对于该任务,data.table包中的transpose
函数可以提供帮助:
unlist(transpose(mydata))
# V11 V12 V13 V21 V22 V23 V31 V32 V33
# 11 12 13 21 22 23 31 32 33
或者unlist(transpose(as.list(mydata)))
。
我想您可能想要跟踪此向量中的值来自的行和列,在这种情况下,您需要关注@ thelatemail的答案或手动构建所有内容:
data.table(
values = unlist(transpose(mydata)),
col = seq_along(mydata),
row = rep(seq(nrow(mydata)), each = length(mydata))
)
# values col row
# 1: 11 1 1
# 2: 12 2 1
# 3: 13 3 1
# 4: 21 1 2
# 5: 22 2 2
# 6: 23 3 2
# 7: 31 1 3
# 8: 32 2 3
# 9: 33 3 3
答案 2 :(得分:2)
R中通常的方法是“按行排名”,这是你似乎正在做的,是使用c(t(yourdata))
方法:
c(t(mydata))
# [1] 11 12 13 21 22 23 31 32 33
如果您希望将其作为单个列矩阵,就像您在答案中所示,请执行:
matrix(c(t(mydata)))
# [,1]
# [1,] 11
# [2,] 12
# [3,] 13
# [4,] 21
# [5,] 22
# [6,] 23
# [7,] 31
# [8,] 32
# [9,] 33
或者,如果您需要有关数据所来自的行和列的信息,您会有一点棘手:
do.call(CJ, lapply(dim(mydata), sequence))[, values := c(t(mydata))][]
# V1 V2 values
# 1: 1 1 11
# 2: 1 2 12
# 3: 1 3 13
# 4: 2 1 21
# 5: 2 2 22
# 6: 2 3 23
# 7: 3 1 31
# 8: 3 2 32
# 9: 3 3 33
这种相当手动的方法可以很快。
示例数据
set.seed(1)
nrow <- 100000
ncol <- 150
DT <- data.table(matrix(sample(100, nrow*ncol, TRUE), nrow = nrow))
<强> 功能 强>
注意:我已经为funFrank
添加了一些优化,使用上面的示例数据将其从约15秒减少到约1秒。优化包括在use.names = FALSE
中使用unlist
并使用seq_len
代替seq
。
funAM <- function(indt) {
setnames(do.call(CJ, lapply(dim(indt), seq_len)),
c("row", "col"))[, value := c(t(indt))][]
}
funThela <- function(indt) {
setkey(melt(indt[,row := .I], id.vars="row"),row)[]
}
funFrank <- function(indt) {
data.table(
values = unlist(transpose(indt), use.names = FALSE),
col = seq_along(indt),
row = rep(seq_len(nrow(indt)), each = length(indt))
)
}
<强> 结果 强>
注意:我已将copy(DT)
用于Thela的方法,因为他们在原始数据集上使用了:=
来创建“行”列。
library(microbenchmark)
microbenchmark(funAM(DT), funThela(copy(DT)), funFrank(DT))
# Unit: milliseconds
# expr min lq mean median uq max neval
# funAM(DT) 163.7426 361.9589 388.9481 388.1012 425.0953 567.3669 100
# funThela(copy(DT)) 583.5059 820.9864 881.4213 881.0558 949.5294 1109.9505 100
# funFrank(DT) 866.5126 1109.7642 1201.5819 1176.9385 1292.6878 1633.0974 100