我有一个矩阵,a
包括9列和R中的1600万行.第4列中的每个元素都是"Apple"或"Lion".
我想在第4列中收集那些具有条目"Apple"的行,并将这个"新"矩阵与第一列中的整数条目进行排序.
执行此操作的最佳方法是什么?当然,输出将是.csv文件,因为无法在R中查看此矩阵(1600万行!!).
我尝试了两个代码:
1)在这段代码中,我首先介绍一个b
全零的9维向量.然后我运行一个for
循环,检查在每一行中a
,第四个元素是否为"Apple".如果是这样,那么该行将被添加b
,并以此方式b
增长.最后我b
使用订单功能排序.
b=rep(0,9) for(i in 1:nrow(a)){ if(a[i,4]=="Apple"){ b=rbind(b,a[i,]) } } b=order(b) write.table(b,"Apple.csv",sep=",",append=TRUE,col.names=FALSE)
这段代码似乎不起作用,因为只运行for循环需要太长时间!!
2)我运行一个for循环,检查每行的第四个条目是否a
为"Apple".如果是这样,它会将该行打印到.csv文件.所以在R中没有创建矩阵.这个.csv文件将在完成后读入R并在将第一列按as.integer
函数转换为整数条目后,我使用order
函数对表进行排序.
for(i in 1:nrow(a)){ if(a[i,4]=="Apple"){ write.table(a[i,],"Apple.csv",sep=",",append=TRUE,col.names=FALSE) } } a=read.csv("Apple.csv") a[,1]=as.integer(a[,1]) a=order(a)
这似乎有效,虽然在我的笔记本电脑上非常慢.按照它的速度,for循环显然需要5天才能完成.我不知道我的笔记本电脑是否具有4 GB RAM本质上无法使用如此庞大的数据集.
我可以在哪些方面优化代码?这个程序最有效的代码是什么?如果有人指出我正确的方向,我会很高兴.
这是另一个使用另一个受欢迎的软件包的答案data.table
.DT就像数据框架,但在类固醇上,在设计上更接近于SQL
library(data.table) DT <- as.data.table(matrix(data = NA, nrow = 20000000, ncol = 9)) DT$V4 <- sample(c("Apple","Lion"), size = 20000000, replace = TRUE, prob = c(0.5, 0.5) ) DT$V9 <- rnorm(20000000, mean = 0, sd = 1000) str(DT) setkey(DT, V9) system.time( r <- setorder( DT[V4 == "Apple"], V9 ) ) str(r) tables()
在我的笔记本电脑上花了
user system elapsed 2.35 0.30 2.64
内存使用
NAME NROW NCOL MB COLS KEY [1,] DT 20,000,000 9 916 V1,V2,V3,V4,V5,V6,V7,V8,V9 V9 [2,] r 9,998,016 9 420 V1,V2,V3,V4,V5,V6,V7,V8,V9 V9 Total: 1,336MB
链接:https: //cran.r-project.org/web/packages/data.table/index.html备忘单:http://blog.datacamp.com/data-table-cheat-sheet/
您应该尝试使用R中为此类工作设计的一些数据争用程序包.它们执行效率极高.下面我使用dplyr
包.
我首先创建了20,000,000行和9列的数据框.然后我设置第4栏为任一Apple
或Lion
随机.然后,我将第9列设置为从以0为中心的正态分布中随机选择,具有较大的标准偏差(以便数字或多或少相隔很远).
我可以过滤Apple并在10秒内对剩余的数据帧进行排序.下面是代码.
> library(dplyr) > > myDF <- as.data.frame(matrix(data = NA, nrow = 20000000, ncol = 9)) > myDF$V4 <- sample(c("Apple","Lion"), size = 20000000, replace= TRUE, prob = c(0.5, 0.5) ) > myDF$V9 <- rnorm(20000000, mean = 0, sd = 1000) > > system.time(AppleOnlySorted <- myDF %>% + filter(V4 == "Apple") %>% + arrange(V9)) user system elapsed 9.165 0.140 9.306 > > head(AppleOnlySorted) V1 V2 V3 V4 V5 V6 V7 V8 V9 1 NA NA NA Apple NA NA NA NA -5053.535 2 NA NA NA Apple NA NA NA NA -4947.533 3 NA NA NA Apple NA NA NA NA -4853.408 4 NA NA NA Apple NA NA NA NA -4848.063 5 NA NA NA Apple NA NA NA NA -4838.298 6 NA NA NA Apple NA NA NA NA -4824.169 > > system.time(AppleOnlySortedDescending <- myDF %>% + filter(V4 == "Apple") %>% + arrange(desc(V9))) user system elapsed 8.948 0.134 9.083
我已经将命令包装在a中system.time
以显示它有多快,但输出保存在AppleOnlySorted
和中AppleOnlySortedDescending
.然后,您可以将该数据框保存为csv或您想要的任何格式.
看myDF
它的大小只有839.2 Mb.因此,假设您的RAM没有加载一堆内存 - 它应该没问题.
> format(object.size(myDF), units = "Mb") [1] "839.2 Mb"
最糟糕的是,你总是可以看看使用bigmemory
软件包把东西写到磁盘上 - 但我怀疑你是否需要这个操作.
希望有所帮助!