我有一个数据框,它是另一个命令的结果。此数据框只有一行,大约有40000个条目。我的问题是3列是一组连接的数据。因此,我想在每第三列之后拆分行,并将其作为新行传输。例如:
创建测试数据框:
df=as.data.frame(matrix(seq(1:12), ncol=12, nrow=1))
现在我的数据框看起来像这样。
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12
1 2 3 4 5 6 7 8 9 10 11 12
但我需要这样:
V1 V2 V3
1 2 3
4 5 6
7 8 9
10 11 12
我怎么能意识到这一点?
答案 0 :(得分:4)
尝试
as.data.frame(matrix(unlist(df, use.names=FALSE),ncol=3, byrow=TRUE))
# V1 V2 V3
#1 1 2 3
#2 4 5 6
#3 7 8 9
#4 10 11 12
或者您可以在matrix
df
as.data.frame(matrix(df, ncol=3, byrow=TRUE))
答案 1 :(得分:2)
还可以尝试使用dim<-
(仅用于常识)
as.data.frame(t(`dim<-`(unlist(df), c(3, 4))))
# V1 V2 V3
# 1 1 2 3
# 2 4 5 6
# 3 7 8 9
# 4 10 11 12
答案 2 :(得分:1)
事实证明这比我预期的要快(虽然仍然没有@akrun采用的明显方法那么快),所以我将发布这个(像大卫一样)“只是为了一般知识”。 (另外,“data.table”所有的东西。): - )
创建一个包含三列的data.table
:
完成后,您可以使用dcast.data.table
获取您提及的输出(加上奖励列)。
对于上面的第2点,我们可以轻松定义类似以下的功能,以便轻松创建群组的过程:
groupMaker <- function(vecLen, perGroup) {
(0:(vecLen-1) %/% perGroup) + 1
}
然后我们可以按如下方式使用它:
dcast.data.table(
data.table(value = unlist(df, use.names = FALSE),
row = groupMaker(ncol(df), 3),
col = 1:3),
row ~ col)
# row 1 2 3
# 1: 1 1 2 3
# 2: 2 4 5 6
# 3: 3 7 8 9
# 4: 4 10 11 12
现在,你提到你实际上正在处理单行~40K列data.frame
(我假设它是39,999列,因为它可以很好地被3整除,我不想打破其他答案)。
记住这一点,这里有一些(无用的)基准测试(没用,因为我们这里正在谈论毫秒)。
set.seed(1)
S <- sample(20, 39999, TRUE)
S <- data.frame(t(S))
funAM <- function(indf) {
dcast.data.table(
data.table(value = unlist(indf, use.names = FALSE),
row = groupMaker(ncol(indf), 3),
col = 1:3),
row ~ col)
}
funDA <- function(indf) {
as.data.frame(t(`dim<-`(unlist(indf), c(3, ncol(indf)/3))))
}
funAK <- function(indf) as.data.frame(matrix(indf, ncol=3, byrow=TRUE))
library(microbenchmark)
microbenchmark(funAM(S), funDA(S), funAK(S))
# Unit: milliseconds
# expr min lq mean median uq max neval
# funAM(S) 18.487001 18.813297 22.105766 18.999891 19.455812 50.25876 100
# funDA(S) 37.187177 37.450893 40.393893 37.870683 38.869726 94.20128 100
# funAK(S) 5.018571 5.149758 5.929944 5.271679 5.536449 26.93281 100
如果 可能 有用,那么所需列的数量和输入列的数量不能很好地相互分割。
例如,尝试以下示例数据:
set.seed(1)
S2 <- sample(20, 40000, TRUE)
S2 <- data.frame(t(S))
使用此示例数据:
funAM
会为您提供warning
,但会正确地将最后一行的最后两列显示为NA
。funAK
会给你一个warning
,但会(可能)错误地回收最后一行的值。funDA
只会给你一个error
。我仍然认为你应该在源头解决问题: - )