当前位置:  开发笔记 > 前端 > 正文

如何在R中更有效地进行拾取和排序?

如何解决《如何在R中更有效地进行拾取和排序?》经验,为你挑选了2个好方法。

我有一个矩阵,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本质上无法使用如此庞大的数据集.

我可以在哪些方面优化代码?这个程序最有效的代码是什么?如果有人指出我正确的方向,我会很高兴.



1> Severin Papp..:

这是另一个使用另一个受欢迎的软件包的答案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/



2> user1357015..:

您应该尝试使用R中为此类工作设计的一些数据争用程序包.它们执行效率极高.下面我使用dplyr包.

我首先创建了20,000,000行和9列的数据框.然后我设置第4栏为任一AppleLion随机.然后,我将第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软件包把东西写到磁盘上 - 但我怀疑你是否需要这个操作.

希望有所帮助!

推荐阅读
个性2402852463
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有