【问题标题】:r - translation of dplyr to data.tabler - dplyr 到 data.table 的翻译
【发布时间】:2020-03-17 15:41:20
【问题描述】:

如何使用 data.table 进行相同的处理?我的意思是,我的 3,5M 行表需要花费大量时间。

数据:

ipoi_pdi <- tibble(
  id = c("1","1","2","3","4","4"),
  tipo_servico = c("Escala Normal", "IFR - 6 horas", "Convocação", "Escala Normal", "Convocação", "Escala Normal")
)

处理:

ipoi_pdi %>%
  group_by(
    id
  ) %>%
  mutate(
    tipo_servico = case_when(
      n() == 1 ~ tipo_servico,
      n() > 1 & any(tipo_servico == "IFR - 6 horas") ~ "IFR - 6 horas",
      n() > 1 & any(tipo_servico == "IFR - 12 horas") ~ "IFR - 12 horas",
     TRUE ~ "Não é IFR"
    )
  ) -> ipoi_pdi

【问题讨论】:

    标签: r dplyr data.table tidyverse


    【解决方案1】:

    有一个非常酷的包可以做这种翻译,叫做dtplyr

    library(dplyr)
    library(dtplyr)
    library(data.table)
    

    您必须对原始代码进行的唯一更改是在运行命令之前将您的对象包装在lazy_dt 中:

    lazy_dt(ipoi_pdi) %>% 
      group_by(
        id
      ) %>%
      mutate(
        tipo_servico = case_when(
          n() == 1 ~ tipo_servico,
          n() > 1 & any(tipo_servico == "IFR - 6 horas") ~ "IFR - 6 horas",
          n() > 1 & any(tipo_servico == "IFR - 12 horas") ~ "IFR - 12 horas",
          TRUE ~ "Não é IFR"
        )
      ) -> ipoi_pdi
    

    现在当您打印对象时,它会将相应的data.table 代码显示为Call

    print(ipoi_pdi)
    #> Source: local data table [?? x 2]
    #> Call:   copy(`_DT1`)[, `:=`(tipo_servico = case_when(.N == 1 ~ tipo_servico, 
    #>     .N > 1 & any(tipo_servico == "IFR - 6 horas") ~ "IFR - 6 horas", 
    #>     .N > 1 & any(tipo_servico == "IFR - 12 horas") ~ "IFR - 12 horas", 
    #>     TRUE ~ "Não é IFR")), keyby = .(id)]
    #> 
    #>   id    tipo_servico 
    #>   <chr> <chr>        
    #> 1 1     IFR - 6 horas
    #> 2 1     IFR - 6 horas
    #> 3 2     Convocação   
    #> 4 3     Escala Normal
    #> 5 4     Não é IFR    
    #> 6 4     Não é IFR    
    #> 
    #> # Use as.data.table()/as.data.frame()/as_tibble() to access results
    

    将您的对象转换为 data.table 并对其运行调用:

    ipoi_pdi_dt <- as.data.table(ipoi_pdi)
    
    ipoi_pdi_dt_new <- ipoi_pdi_dt[, `:=`(tipo_servico = case_when(.N == 1 ~ tipo_servico, 
                                                                   .N > 1 & any(tipo_servico == "IFR - 6 horas") ~ "IFR - 6 horas", 
                                                                   .N > 1 & any(tipo_servico == "IFR - 12 horas") ~ "IFR - 12 horas", 
                                                                   TRUE ~ "Não é IFR")), keyby = .(id)]
    
    print(ipoi_pdi_dt_new)
    #>    id  tipo_servico
    #> 1:  1 IFR - 6 horas
    #> 2:  1 IFR - 6 horas
    #> 3:  2    Convocação
    #> 4:  3 Escala Normal
    #> 5:  4     Não é IFR
    #> 6:  4     Não é IFR
    

    检查结果是否相等:

    all.equal(as.data.frame(ipoi_pdi_new), as.data.frame(ipoi_pdi_dt_new))
    #> [1] TRUE
    

    由于data.table 没有case_when 的等价物,因此该部分保持不变。如果您出于性能原因这样做,那应该没问题。否则你必须使用一堆ifelse 调用来替换它。

    【讨论】:

    • data.table 很快就会有fcase(),开发版已经有。更多信息在这里:github.com/Rdatatable/data.table/blob/master/NEWS.md。另外:在处理这样的大量数据时,避免复制或使用copy()
    • 很高兴知道!我猜他们会在 dtplyr 上实现它,一旦它在 CRAN 上。
    【解决方案2】:
    setDT(ipoi_pdi)
    ipoi_pdi[, 
             tipo_servico := 
               if (.N == 1) {
                 tipo_servico
               } else if (any(tipo_servico == "IFR - 6 horas")) {
                 "IFR - 6 horas"
               } else if (any(tipo_servico == "IFR - 12 horas")) {
                 "IFR - 12 horas"
               } else {
                 "Não é IFR"
               },
             by = id]
    

    PS。在第一个if之后我们不需要再次检查.N &gt; 1,我们知道它一定是真的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-25
      • 2022-01-18
      • 2016-11-18
      • 1970-01-01
      • 2018-03-18
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多