【问题标题】:Subset from a list and merge together列表中的子集并合并在一起
【发布时间】:2018-08-23 14:46:05
【问题描述】:
my.list <- list()
for(i in 1:2){
  df <- data.frame(year = rep(1980:1981, each = 4), day = rnorm(2*4))
  my.list[[i]] <- df
 }

从列表的每个元素中,我想提取年份并绑定在一起。 即从my.list[[1]]my.list[[2]],提取1980 年的数据并绑定行,然后从my.list[[1]]my.list[[2]],提取1981 年的数据。我可以这样做:

df <- rbindlist(my.list)
df %>% dplyr::filter(year == 1980)
df %>% dplyr::filter(year == 1981)

但是,我想知道是否有直接从列表中提取子集的方法 使用rbindlist

【问题讨论】:

  • rnorm(2*4) 为什么不rnorm(8)
  • 样本输出是什么?
  • 对于year==1980,您可以使用lapply(my.list, function(x) x[x$year==1980,])

标签: r list dplyr subset


【解决方案1】:

也许:

purrr::map_df(my.list,~ dplyr::filter(.,year=="1980"))
purrr::map_df(my.list,~ dplyr::filter(.,year=="1981"))

【讨论】:

    【解决方案2】:

    您可以从dplyr 使用bind_rows()

    my.list %>% 
      bind_rows() %>%
      filter(year == "1980")
    

    或者后跟split:

    df <- my.list %>% 
      bind_rows() %>%
      filter(year == "1980")
    
    split(df, df$year)
    #
    $`1980`
       year        day
    1  1980  1.3974267
    2  1980  1.7636530
    3  1980  0.4856014
    4  1980 -0.2657389
    9  1980 -0.2607259
    10 1980  0.9618104
    11 1980  0.8538955
    12 1980  0.4187967
    
    $`1981`
       year        day
    5  1981  0.1516114
    6  1981  1.3766098
    7  1981 -0.1803943
    8  1981 -1.5676751
    13 1981  0.3399565
    14 1981  0.5964251
    15 1981  1.8714180
    16 1981  0.6028704
    

    【讨论】:

    • 谢谢,但我避免使用 bind rows 位,因为我的列表很大,因此当它尝试绑定时,我的内存不足
    【解决方案3】:

    有趣的问题 - 我设计了一个小测试,以了解不同功能在速度和内存方面的比较。

    library(dplyr)
    library(rbenchmark)
    library(data.table)
    

    数据

    dataList <- function(nobvs = 500, nelements = 2){
      return(lapply(1:nelements, function(k){
        return(data.table(year = rep(1980:1981, each = nobvs), 
                          day = rnorm(2*nobvs)))
      } ))
    }
    

    代码

    比较函数

    fnRbindlist <- function(ll = data_list){
      return(rbindlist(l = ll, use.names = T, fill = T)[year == 1980])
    }
    
    fnBindRows <- function(ll = data_list){
      return(ll %>% bind_rows() %>% filter(year == 1980))
    }
    
    fnPurr <- function(ll = data_list){
      return(purrr::map_df(ll, ~ dplyr::filter(., year == 1980)))
    }
    
    fnSubsetRbind <- function(ll = data_list){
      mm <- lapply(ll, function(k) return(k[year == 1980]))
      return(rbindlist(mm, use.names = T, fill = T))
    }
    

    比较速度

    speed_results <- lapply(c(100, 1000, 10000), function(q){
      nobvs <- q
      nelements <- 2
      dat <- benchmark(fnRbindlist(dataList(nobvs, nelements)), 
                       fnBindRows(dataList(nobvs, nelements)),
                       fnPurr(dataList(nobvs, nelements)),
                       fnSubsetRbind(dataList(nobvs, nelements)), 
                       replications = 1000, 
                       order = 'elapsed', 
                       columns = c('test', 'replications', 'elapsed'))
      dat$rank <- 1:nrow(dat)
      dat$nobvs <- nobvs
      dat$nelements <- nelements
      return(dat)
    })
    

    比较内存使用情况

    memory_results <- lapply(c(100, 1000, 10000), function(q){
      nobvs <- q
      nelements <- 2
      dat <- data.table(memRbindlist = pryr::mem_change(fnRbindlist(dataList(nobvs, nelements))), 
                        memBindRows = pryr::mem_change(fnBindRows(dataList(nobvs, nelements))),
                        memPurr = pryr::mem_change(fnPurr(dataList(nobvs, nelements))),
                        memSubsetRbind = pryr::mem_change(fnSubsetRbind(dataList(nobvs, nelements))))
      dat$nobvs <- nobvs
      dat$nelements <- nelements
      return(dat)
    })
    

    结果

    > rbindlist(l = speed_results, use.names = T, fill = T)[order(test)]
                                             test replications elapsed rank nobvs nelements
     1:    fnBindRows(dataList(nobvs, nelements))         1000    1.75    1   100         2
     2:    fnBindRows(dataList(nobvs, nelements))         1000    2.23    1  1000         2
     3:    fnBindRows(dataList(nobvs, nelements))         1000    6.95    1 10000         2
     4:        fnPurr(dataList(nobvs, nelements))         1000    2.56    3   100         2
     5:        fnPurr(dataList(nobvs, nelements))         1000    3.02    3  1000         2
     6:        fnPurr(dataList(nobvs, nelements))         1000    8.89    4 10000         2
     7:   fnRbindlist(dataList(nobvs, nelements))         1000    2.56    2   100         2
     8:   fnRbindlist(dataList(nobvs, nelements))         1000    2.85    2  1000         2
     9:   fnRbindlist(dataList(nobvs, nelements))         1000    8.17    2 10000         2
    10: fnSubsetRbind(dataList(nobvs, nelements))         1000    3.77    4   100         2
    11: fnSubsetRbind(dataList(nobvs, nelements))         1000    4.04    4  1000         2
    12: fnSubsetRbind(dataList(nobvs, nelements))         1000    8.77    3 10000         2
    
    
    > rbindlist(l = memory_results, use.names = T, fill = T)
       memRbindlist memBindRows memPurr memSubsetRbind nobvs nelements
    1:       -34944       69272   70104         220672   100         2
    2:        51312       69272   70104         220672  1000         2
    3:        51416       69272   70104         220672 10000         2
    

    基于上述,我想说rbindlist 是最好的选择,因为它的速度始终如一并且内存使用量最少(OP 中的主要问题)。

    希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 2017-01-28
      • 2021-02-13
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      • 2019-04-16
      相关资源
      最近更新 更多