Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
提高write.table的性能_R - Fatal编程技术网

提高write.table的性能

提高write.table的性能,r,R,我有一个data.frame,我想把它写出来。mydata.frame的维度是256行乘65536列。除了write.csv,还有什么更快的替代方案 如果您的所有列都属于同一类,则在写入之前将其转换为矩阵,这样可以将速度提高近6倍。此外,您还可以研究使用包MASS中的write.matrix()。也许我没有正确设置一些东西: #Fake data m <- matrix(runif(256*65536), nrow = 256) #AS a data.frame system.time(w

我有一个
data.frame
,我想把它写出来。my
data.frame
的维度是256行乘65536列。除了
write.csv
,还有什么更快的替代方案

如果您的所有列都属于同一类,则在写入之前将其转换为矩阵,这样可以将速度提高近6倍。此外,您还可以研究使用包
MASS
中的
write.matrix()。也许我没有正确设置一些东西:

#Fake data
m <- matrix(runif(256*65536), nrow = 256)
#AS a data.frame
system.time(write.csv(as.data.frame(m), "dataframe.csv"))
#----------
#   user  system elapsed 
# 319.53   13.65  333.76 

#As a matrix
system.time(write.csv(m, "matrix.csv"))
#----------
#   user  system elapsed 
#  52.43    0.88   53.59 

#Using write.matrix()
require(MASS)
system.time(write.matrix(m, "writematrix.csv"))
#----------
#   user  system elapsed 
# 113.58   59.12  172.75 
因此,这并不是什么大问题,也不像下面的评论所认为的那样歪曲信息。如果您仍然不确信在大数据帧上使用
write.csv()
是一个坏主意,请参阅
注释下的手册:

write.table can be slow for data frames with large numbers (hundreds or more) of
columns: this is inevitable as each column could be of a different class and so must be
handled separately. If they are all of the same class, consider using a matrix instead.

最后,考虑到如果你仍在睡眠中超速保存,则移动到本地RDATA对象

system.time(save(m2, file = "thisisfast.RData"))
#   user  system elapsed 
#  21.67    0.12   21.81
data.table::fwrite()
由Otto Seiskari提供,版本为1.9.8+。Matt在顶部做了额外的增强(包括并行化),并对此进行了描述。请在网上报告任何问题

首先,这里比较了@chase在上面使用的相同维度(即大量列:65000列(!)x256行),以及
fwrite
write\u feather
,因此我们在机器之间有一定的一致性。注意
compress=FALSE
在基数R中造成的巨大差异

# -----------------------------------------------------------------------------
# function  | object type |  output type | compress= | Runtime | File size |
# -----------------------------------------------------------------------------
# save      |      matrix |    binary    |   FALSE   |    0.3s |    134MB  |
# save      |  data.frame |    binary    |   FALSE   |    0.4s |    135MB  |
# feather   |  data.frame |    binary    |   FALSE   |    0.4s |    139MB  |
# fwrite    |  data.table |    csv       |   FALSE   |    1.0s |    302MB  |
# save      |      matrix |    binary    |   TRUE    |   17.9s |     89MB  |
# save      |  data.frame |    binary    |   TRUE    |   18.1s |     89MB  |
# write.csv |      matrix |    csv       |   FALSE   |   21.7s |    302MB  |
# write.csv |  data.frame |    csv       |   FALSE   |  121.3s |    302MB  |
请注意,
fwrite()
并行运行。这里显示的计时是在13英寸Macbook Pro上进行的,它有2个内核和1个线程/内核(通过超线程增加2个虚拟线程)、512GB SSD、256KB/内核二级缓存和4MB四级缓存。根据您的系统规格,YMMV

我还根据相对更可能(和更大)的数据重新运行基准:

library(data.table)
NN <- 5e6 # at this number of rows, the .csv output is ~800Mb on my machine
set.seed(51423)
DT <- data.table(
  str1 = sample(sprintf("%010d",1:NN)), #ID field 1
  str2 = sample(sprintf("%09d",1:NN)),  #ID field 2
  # varying length string field--think names/addresses, etc.
  str3 = replicate(NN,paste0(sample(LETTERS,sample(10:30,1),T), collapse="")),
  # factor-like string field with 50 "levels"
  str4 = sprintf("%05d",sample(sample(1e5,50),NN,T)),
  # factor-like string field with 17 levels, varying length
  str5 = sample(replicate(17,paste0(sample(LETTERS, sample(15:25,1),T),
      collapse="")),NN,T),
  # lognormally distributed numeric
  num1 = round(exp(rnorm(NN,mean=6.5,sd=1.5)),2),
  # 3 binary strings
  str6 = sample(c("Y","N"),NN,T),
  str7 = sample(c("M","F"),NN,T),
  str8 = sample(c("B","W"),NN,T),
  # right-skewed (integer type)
  int1 = as.integer(ceiling(rexp(NN))),
  num2 = round(exp(rnorm(NN,mean=6,sd=1.5)),2),
  # lognormal numeric that can be positive or negative
  num3 = (-1)^sample(2,NN,T)*round(exp(rnorm(NN,mean=6,sd=1.5)),2))

# -------------------------------------------------------------------------------
# function  |   object   | out |        other args         | Runtime  | File size |
# -------------------------------------------------------------------------------
# fwrite    | data.table | csv |      quote = FALSE        |   1.7s   |  523.2MB  |
# fwrite    | data.frame | csv |      quote = FALSE        |   1.7s   |  523.2MB  |
# feather   | data.frame | bin |     no compression        |   3.3s   |  635.3MB  |
# save      | data.frame | bin |     compress = FALSE      |  12.0s   |  795.3MB  |
# write.csv | data.frame | csv |    row.names = FALSE      |  28.7s   |  493.7MB  |
# save      | data.frame | bin |     compress = TRUE       |  48.1s   |  190.3MB  |
# -------------------------------------------------------------------------------

另一个选项是使用文件格式

df <- as.data.frame(matrix(runif(256*65536), nrow = 256))

system.time(feather::write_feather(df, "df.feather"))
#>   user  system elapsed 
#>  0.237   0.355   0.617 
现在,这是一个有点不公平的比较,因为
saveRDS
的默认值是压缩数据,而这里的数据是不可压缩的,因为它是完全随机的。关闭压缩功能会大大加快存储速度:

system.time(saveRDS(df, "df.rds", compress = FALSE))
#>   user  system elapsed 
#>  0.181   0.247   0.473     
事实上,它现在比羽毛稍微快一点。那为什么要用羽毛呢?嗯,它通常比
readRDS()
要快,而且与读取数据的次数相比,写入数据的次数相对较少

system.time(readRDS("df.rds"))
#>   user  system elapsed 
#>  0.198   0.090   0.287 

system.time(feather::read_feather("df.feather"))
#>   user  system elapsed 
#>  0.125   0.060   0.185 

您还可以尝试“readr”包的read_rds(与data.table::fread比较)和write_rds(与data.table::fwrite比较)

下面是我的数据集中的一个简单示例 (1133行和429499列):

写入数据集
fwrite(rankp2,file=“rankp2_429499.txt”,col.names=T,row.names=F,quote=F,sep=“\T”)
write_rds(rankp2,“rankp2_429499.rds”)

读取数据集(1133行和429499列)
system.time(fread(“rankp2_429499.txt”,sep=“\t”,header=t,fill=TRUE))
 用户系统运行时间
42.391 0.526 42.949

system.time(读取rds(“rankp2\u 429499.rds”))
用户系统运行时间
2.157 0.388 2.547

希望有帮助。

用于快速读取和写入数据文件的最新选项是
fst
以二进制格式生成文件

使用
write.fst(dat,“file.fst”,compress=0)
,其中
compress
可以从0(无压缩)变为100(最大压缩)。可以使用
dat=read.fst(“file.fst”)
将数据读回R。根据中列出的计时,它比
feather
data.table
和base R
readRDS
writers


软件包开发网站警告说,
fst
数据格式仍在发展中,因此不应将
fst
用于长期数据存储。

我认为您应该使用fwrite()

速度快得多,对我帮助很大:

fwrite(x, file = "", append = FALSE, quote = "auto",
  sep = ",", sep2 = c("","|",""),
  eol = if (.Platform$OS.type=="windows") "\r\n" else "\n",
  na = "", dec = ".", row.names = FALSE, col.names = TRUE,
  qmethod = c("double","escape"),
  logical01 = getOption("datatable.logical01", FALSE),  # due to change to TRUE; see NEWS
  logicalAsInt = logical01,  # deprecated
  dateTimeAs = c("ISO","squash","epoch","write.csv"),
  buffMB = 8L, nThread = getDTthreads(),
  showProgress = interactive(),
  verbose = getOption("datatable.verbose", FALSE))

或者使用更快的硬盘,或者如果您的数据可以转换为矩阵,请使用
write
。但当我第一次将其导入R use read.table时,它会自动使用dataframe,因此,在我完成计算后,我需要使用as.matrix?您需要将其写为CSV,还是可以将其保存为RData对象或其他压缩形式?我希望输出的文件看起来像一个矩阵,它将有单独的列和行。@lolibility-我想我的问题更多的是为什么需要它看起来像一个矩阵?你是打算在另一个程序中打开它,还是将它输入到其他程序中?或者,您只需要保存,以便以后可以在R中提取它。正如我在下面所展示的,原生R对象可以更快地保存并占用更少的空间。在下面的例子中,CSV文件需要约275MB,而RData对象需要约80MB。这有点不公平的比较。。。as.data.frame需要相当长的时间。此外,OP拥有的数据已经在data.frame中。@John-这很好,尽管与使用
write.csv()
和朋友在
data.frame
matrix
上的开销相比,
as.data.frame
的相对开销可以忽略不计。我知道这要少一些,但是最好有可能被接受的答案,而不是让天真的读者去回答这个问题。@John-是的,我完全同意。谢谢你朝着正确的方向轻推。老实说,我只是草率行事,但我想给出的不仅仅是
RTFM
的回应。另外,
as.data.frame()
的开销也会增加,因为在最终的
system.time(save(…)
中,添加
compress=FALSE
要快得多。在我的机器上是14秒,而不是0.2秒。有关想要测试它的人的要点,请参阅。FWIW,fwrite对于CSV来说速度很快,但与feather不在同一级别。请注意
saveRDS
需要
compress=FALSE
feather
很好,但与原始问题无关。因为它是二进制格式…@DmitriySeliva
system.time(saveRDS(df, "df.rds"))
#>   user  system elapsed 
#> 17.363   0.307  17.856
system.time(saveRDS(df, "df.rds", compress = FALSE))
#>   user  system elapsed 
#>  0.181   0.247   0.473     
system.time(readRDS("df.rds"))
#>   user  system elapsed 
#>  0.198   0.090   0.287 

system.time(feather::read_feather("df.feather"))
#>   user  system elapsed 
#>  0.125   0.060   0.185 
fwrite(x, file = "", append = FALSE, quote = "auto",
  sep = ",", sep2 = c("","|",""),
  eol = if (.Platform$OS.type=="windows") "\r\n" else "\n",
  na = "", dec = ".", row.names = FALSE, col.names = TRUE,
  qmethod = c("double","escape"),
  logical01 = getOption("datatable.logical01", FALSE),  # due to change to TRUE; see NEWS
  logicalAsInt = logical01,  # deprecated
  dateTimeAs = c("ISO","squash","epoch","write.csv"),
  buffMB = 8L, nThread = getDTthreads(),
  showProgress = interactive(),
  verbose = getOption("datatable.verbose", FALSE))