以下代码将向量与数据框组合在一起:
newrow = c(1:4) existingDF = rbind(existingDF,newrow)
但是,此代码始终在数据帧的末尾插入新行。
如何在数据框中的指定点插入行?例如,假设数据框有 20 行,如何在第 10 行和第 11 行之间插入新行?
这是一个避免(通常很慢)rbind调用的解决方案:
rbind
existingDF <- as.data.frame(matrix(seq(20),nrow=5,ncol=4)) r <- 3 newrow <- seq(4) insertRow <- function(existingDF, newrow, r) { existingDF[seq(r+1,nrow(existingDF)+1),] <- existingDF[seq(r,nrow(existingDF)),] existingDF[r,] <- newrow existingDF } > insertRow(existingDF, newrow, r) V1 V2 V3 V4 1 1 6 11 16 2 2 7 12 17 3 1 2 3 4 4 3 8 13 18 5 4 9 14 19 6 5 10 15 20
如果速度不如清晰度重要,那么@Simon 的解决方案效果很好:
existingDF <- rbind(existingDF[1:r,],newrow,existingDF[-(1:r),]) > existingDF V1 V2 V3 V4 1 1 6 11 16 2 2 7 12 17 3 3 8 13 18 4 1 2 3 4 41 4 9 14 19 5 5 10 15 20
(注意我们的索引r不同)。
r
最后,基准测试:
library(microbenchmark) microbenchmark( rbind(existingDF[1:r,],newrow,existingDF[-(1:r),]), insertRow(existingDF,newrow,r) ) Unit: microseconds expr min lq median uq max 1 insertRow(existingDF, newrow, r) 660.131 678.3675 695.5515 725.2775 928.299 2 rbind(existingDF[1:r, ], newrow, existingDF[-(1:r), ]) 801.161 831.7730 854.6320 881.6560 10641.417
基准
正如@MatthewDowle 总是向我指出的那样,随着问题规模的增加,需要检查基准以进行扩展。那么我们开始吧:
benchmarkInsertionSolutions <- function(nrow=5,ncol=4) { existingDF <- as.data.frame(matrix(seq(nrow*ncol),nrow=nrow,ncol=ncol)) r <- 3 # Row to insert into newrow <- seq(ncol) m <- microbenchmark( rbind(existingDF[1:r,],newrow,existingDF[-(1:r),]), insertRow(existingDF,newrow,r), insertRow2(existingDF,newrow,r) ) # Now return the median times mediansBy <- by(m$time,m$expr, FUN=median) res <- as.numeric(mediansBy) names(res) <- names(mediansBy) res } nrows <- 5*10^(0:5) benchmarks <- sapply(nrows,benchmarkInsertionSolutions) colnames(benchmarks) <- as.character(nrows) ggplot( melt(benchmarks), aes(x=Var2,y=value,colour=Var1) ) + geom_line() + scale_x_log10() + scale_y_log10()
@Roland 的解决方案可以很好地扩展,即使调用rbind:
5 50 500 5000 50000 5e+05 insertRow2(existingDF, newrow, r) 549861.5 579579.0 789452 2512926 46994560 414790214 insertRow(existingDF, newrow, r) 895401.0 905318.5 1168201 2603926 39765358 392904851 rbind(existingDF[1:r, ], newrow, existingDF[-(1:r), ]) 787218.0 814979.0 1263886 5591880 63351247 829650894
以线性比例绘制:
和对数比例: