【问题标题】:Subset data frames in a list meeting a particular changing condition列表中满足特定变化条件的子集数据框
【发布时间】:2018-02-26 20:17:36
【问题描述】:

假设我在一个列表 (my.ls) 中有 2 个数据框(d1 和 d2)。我想根据条件对每个数据帧进行子集化(例如,变量c 等于某些字母,例如l、m 和n)并将所有这些子集数据帧保存在不同的列表中。

我可以对每个条件使用lapply 来完成它,但它非常冗长。除了for loop 之外,是否有可能以更智能的方式做到这一点?也许是mapply?

d1<-data.frame(a=5:1, b=c(rep(2006, times=4),NA), c = letters[10:14])
d2<-data.frame(a=1:5, b=c(2007, 2007, NA, NA, 2007), c = letters[12:16])  

my.ls <- list(d1 = d1, d2 = d2)

my_ls_l <- lapply(my.ls, subset, c=="l")
my_ls_m <- lapply(my.ls, subset, c=="m")
my_ls_n <- lapply(my.ls, subset, c=="n")

my_ls_all <- c(my_ls_l,my_ls_m,my_ls_n)

c_values <- c("l","m","n")

  # Bit of code that does not work
my_ls_smart <- mapply(subset,my.ls,c_values)

【问题讨论】:

  • 你的意思是lapply(my.ls, function(i) i[i$c %in% c('l', 'm', 'n'),])?
  • @Sotos 将产生 2 个数据帧的列表,其中 c 等于 l、m 或 n。我正在考虑获取 6 个数据帧,d1 和 c==l,d1 和 c==m,...,d2 和 c == n
  • Fwiw,维护和创建具有相同列的单独数据框在 R 中几乎总是一个坏主意......我只会做 library(data.table); rbindlist(my.ls, id="src")[c %in% c_values] 并停在那里。
  • @Frank 完全同意,这只是以客户想要的方式呈现输出的最后一步。

标签: r data.table subset apply lapply


【解决方案1】:

这是一个基本的 R 解决方案。我们首先将lapply 用于子集,然后将split 用于var c。要删除长度为 0 的数据帧,我们使用 Filter(nrow,...)

lapply(my.ls, function(i) {x <- i[i$c %in% c('l', 'm', 'n'),]; 
                           Filter(nrow, split(x, x$c))
                           #or avoid Filter by split(x, x$c, drop = TRUE) (from @Nate)
                           })

【讨论】:

  • 或者我们可以使用split(x, x$c, drop = TRUE)而不是调用Filter
【解决方案2】:

这样就可以了:

library(purrr)

c_values %>% map(function(x) map(my.ls, ~subset(., c == x)))

[[1]]
[[1]]$d1
  a    b c
3 3 2006 l

[[1]]$d2
  a    b c
1 1 2007 l


[[2]]
[[2]]$d1
  a    b c
4 2 2006 m

[[2]]$d2
  a    b c
2 2 2007 m


[[3]]
[[3]]$d1
  a  b c
5 1 NA n

[[3]]$d2
  a  b c
3 3 NA n

说明:您将map c_values 中的每个值放入一个 map 函数中,该函数迭代每个 dataframe 并将其设置为 c_values 中的每个 value。

【讨论】:

    【解决方案3】:

    这里有mapply的解决方案

    #your data
    d1<-data.frame(a=5:1, b=c(rep(2006, times=4),NA), c = letters[10:14])
    d2<-data.frame(a=1:5, b=c(2007, 2007, NA, NA, 2007), c = letters[12:16])  
    my.ls <- list(d1=d1, d2=d2)
    c_values <- list(c("l","m", "n"))
    #result
    lapply(mapply(function(i,j){subset(i, c %in% j)}, my.ls, c_values, SIMPLIFY=F),
       function(x) split(x, x$c, drop = T))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-22
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多