【问题标题】:setdiff for a list of dataframes without using a loop不使用循环的数据帧列表的 setdiff
【发布时间】:2017-09-25 21:22:18
【问题描述】:

我有一个按年份索引的 data.frames 列表,我想在这些嵌套 data.frames 中的列和单独的向量之间使用setdiff

对于 data.frames a 和向量 b 的列表。现在我正在遍历元素

for (i in a) {
    missing_values = setdiff(x = b, y = i$col1)
    print(missing_values)                            #this has what I want
    store_values[i$year[[1]]] = list(missing_values) #actually this doesn't work as expected but not sure why
     }
setdiff(x = b, y = a$'2010'$col1) #returns what I want for 1 data.frame

除了循环还有其他方法吗?

store_values
[[1]]
[1] NA

[[2]]
[1] NA

[[3]]
[1] NA

[[4]]
[1] NA

不确定这个问题是否需要样本数据,但如果需要,我可以提供一些。

样本数据:

df <- data.frame(matrix(ncol = 2, nrow = 4))
colnames(df) <- c('col1', 'year')
df$col1 <- c('a', 'b', 'c', 'd')
df$year <- c(2010, 2010, 2011, 2011)
df <- split(df, df$year)

b <- c('a', 'g')
setdiff(x = b, y = df$`2010`$col1) #g

store_values <- ls()
for (i in df){
  missing_values <- setdiff(x = b, y = i$col1)
  print(missing_values)                              # good
  store_values[i$year[[1]]] <- list(missing_values)  # no good
}

【问题讨论】:

  • 你确定a$'2010'$col1返回你想要的吗?无论如何,您应该提供 a 和 b 以使其可重现,..
  • @BigDataScientist 添加了一些示例数据
  • 在我看来,按年分割 df 是一个相当糟糕的主意。现在,您将年份存储为数字和字符串(每个 df 的名称),并且必须在此处和每个后续步骤中进行循环或 lapply 之类的扭曲)...使用 data.table,您可以这样做fsetdiff(CJ(col1 = b, year = unique(DT$year)), DT) 或类似的 dplyr 的 setdiff 以及 expand.grid。
  • @Frank 从未真正使用过data.tables,在这种情况下我是否必须将df 更改为data.table
  • 你说的太对了。 lapply 是我新的最大敌人。真是一场灾难。

标签: r dataframe


【解决方案1】:

一种简单的方法是将所有内容保存在 data.frame 中:

library(tidyverse)

df = data_frame(col1 = c('a', 'b', 'c', 'd'),
                year = c(2010, 2010, 2011, 2011))
b <- c('a', 'g')

df %>% group_by(year) %>% 
    summarise(missing_vals = list(setdiff(b, col1))) %>% 
    unnest()
#> # A tibble: 3 × 2
#>    year missing_vals
#>   <dbl>        <chr>
#> 1  2010            g
#> 2  2011            a
#> 3  2011            g

在基础 R 中可能会转换为

do.call(rbind, 
        apply(aggregate(col1 ~ year, df, 
                        function(x){setdiff(b, x)}), 
              1, data.frame))
#>   year col1
#> 1 2010    g
#> 2 2011    a
#> 3 2011    g

从这一点开始,可以很容易地进行按yearcol1 分组的进一步操作。

【讨论】:

    【解决方案2】:

    你可以使用lapply:

    res <- lapply(df, FUN = function(x) {
      setdiff(x = b, y = x$col1)
    })
    res
    
    $`2010`
    [1] "g"
    
    $`2011`
    [1] "a" "g"
    

    【讨论】:

    • 确实如此。它甚至为您提供您想要的输出格式(如果我没记错的话)作为其默认格式;)
    猜你喜欢
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多