Lan*_*ter 3 sorting for-loop r time-complexity
我有一个矩阵,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)
Run Code Online (Sandbox Code Playgroud)
这段代码似乎不起作用,因为只运行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)
Run Code Online (Sandbox Code Playgroud)
这似乎有效,虽然在我的笔记本电脑上非常慢.按照它的速度,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()
Run Code Online (Sandbox Code Playgroud)
在我的笔记本电脑上花了
user system elapsed
2.35 0.30 2.64
Run Code Online (Sandbox Code Playgroud)
内存使用
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
Run Code Online (Sandbox Code Playgroud)
链接: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
Run Code Online (Sandbox Code Playgroud)
我已经将命令包装在a中system.time以显示它有多快,但输出保存在AppleOnlySorted和中AppleOnlySortedDescending.然后,您可以将该数据框保存为csv或您想要的任何格式.
看myDF它的大小只有839.2 Mb.因此,假设您的RAM没有加载一堆内存 - 它应该没问题.
> format(object.size(myDF), units = "Mb")
[1] "839.2 Mb"
Run Code Online (Sandbox Code Playgroud)
最糟糕的是,你总是可以看看使用bigmemory软件包把东西写到磁盘上 - 但我怀疑你是否需要这个操作.
希望有所帮助!