微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

spec_tbl_df 在与普通 tibble 相同的操作上慢 10 倍以上

如何解决spec_tbl_df 在与普通 tibble 相同的操作上慢 10 倍以上

所以我真的很想知道为什么使用相同数据的两个不同的 R 会话会产生截然不同的时间来完成相同的任务。 在多次重启 R、清除所有变量并真正运行干净的 R 之后,我发现了问题:vroomreadr 提供的新数据结构由于某种原因非常缓慢在我的剧本上。当然,解决此问题的最简单方法是在加载数据后立即将其转换为小标题。 或者是否有其他解释,例如我的函数中糟糕的编码实践可以解释缓慢的行为?或者,这是这些软件包最近更新的错误吗?如果是这样,并且如果有人在向 tidyverse 报告错误方面更有经验,那么这里有一个 repex 显示行为,因为我觉得这超出了我的范围。

#Load packages
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter,lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect,setdiff,setequal,union
library(purrr)
library(vroom)
library(tidyr)
library(microbenchmark)
#Genenrate some dummy data
ex_data <- tibble(
  sd = 1,mean = 1:1000,a1 = rnorm(1000,mean,sd),a2 = rnorm(1000,a3 = rnorm(1000,sd)
  ) %>% 
  mutate(
    a1 = if_else(a1<mean,NA_real_,a1),a2 = if_else(a2<mean,a2),a3 = if_else(a3<mean,a3)
  )
#Wrapper function discovering the behavIoUre
impute_row <- function(mean,sd,data){
  if(!anyNA(data)){
    return(data)
  }else{
    data <- as.data.frame(data)
    data[is.na(data)] <-  rnorm(n = sum(is.na(data)),mean = mean,sd = sd)
    return(data)
  }
}
#Main function
imputer <- function(data){
  data %>% 
    mutate(
      data = pmap(list(mean,data),impute_row)
    ) %>% 
    unnest(cols = data)
}
#Generate dummy file
out_file <- tempfile(fileext = "csv")
vroom_write(ex_data,out_file,",")
#Read it in
ex_data_spc <- vroom(out_file,col_types = cols()) %>% 
  nest(data = -c(mean,sd))
#nest the original data as well
ex_data <- ex_data %>% 
  nest(data = -c(mean,sd))
#Benchmark
microbenchmark(
  tib = imputer(ex_data),spc_tib = imputer(ex_data_spc),times = 10
)
#> Unit: milliseconds
#>     expr        min         lq       mean     median        uq       max neval
#>      tib   82.81192   87.45288   89.19118   90.47263   91.2216   93.4418    10
#>  spc_tib 1041.90378 1070.00579 1244.97090 1076.92022 1093.0054 2780.0722    10

reprex package (v2.0.0) 于 2021 年 6 月 14 日创建

在最坏的情况下,它比在 tibble 上运行要慢近 30 倍。

解决方法

This 是我想到的问题。众所周知,这些问题发生在 vroom 上,而不是发生在 spec_tbl_df 类上,后者实际上没有太大作用。

vroom 做各种事情来尝试加快阅读速度; AFAIK 主要是通过懒惰阅读。这就是在比较两个数据集时获得所有这些不同组件的方式。

使用 vroom:

~~~(snip)~~~
ex_data_spc <- vroom(out_file,col_types = cols()) %>% 
  nest(data = -c(mean,sd))
~~~(snip)~~~

#> Unit: milliseconds
#>     expr       min        lq     mean    median        uq       max neval cld
#>  spc_tib 1679.2088 1704.3085 2106.864 1731.6694 1942.9444 4918.4498    10   b
#>      tib  149.8716  158.8548  169.489  170.3735  182.5681  192.8533    10  a

all.equal(ex_data,ex_data_spc)
#>    [1] "Component \"data\": Component 1: Attributes: < Names: 1 string mismatch >"                                                 
#>    [2] "Component \"data\": Component 1: Attributes: < Length mismatch: comparison on first 2 components >"                        
#>    [3] "Component \"data\": Component 1: Attributes: < Component \"class\": Lengths (3,4) differ (string compare on first 3) >"   
#>    [4] "Component \"data\": Component 1: Attributes: < Component \"class\": 3 string mismatches >"                                 
#>    [5] "Component \"data\": Component 1: Attributes: < Component 2: Modes: numeric,externalptr >"  
                               
~~~(snip)~~~

带阅读器:

~~~(snip)~~~
ex_data_spc <- readr::read_csv(out_file,sd))
~~~(snip)~~~
#> Unit: milliseconds
#>     expr      min       lq     mean   median       uq      max neval cld
#>  spc_tib 148.9432 161.7315 181.2137 184.4592 191.9048 219.7883    10   a
#>      tib 161.9441 166.7826 175.3644 175.3354 181.4598 197.5544    10   a

all.equal(ex_data,ex_data_spc)
#> [1] TRUE

如果您愿意,可以将您的 reprex 发布到该问题上。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。