【问题标题】:R lapply for list of lists to apply the same function to pre-defined columnsR lapply 用于列表列表以将相同的功能应用于预定义的列
【发布时间】:2020-12-27 22:05:09
【问题描述】:

我有一个列表列表(2 个 df)并想使用 lapply 为每个 df 中的预定义列执行相同的功能。

我特别想使用 DescTools 包中的 winsorize 函数。目前我知道如何通过在 function(x) 命令中指定所有单独的列来做到这一点,但是,如果我有很多列,这会很乏味(参见示例)。

应用该函数后,应返回包含转换后变量的整个列表列表(所有列)。理想情况下,转换后的变量使用“_w”(例如“price_w”)或类似名称进行扩展,以表明这些是经过优化的变量。

我的数据如下所示,尽管我只想将该函数应用于预定义的“价格”和“质量”列。

id <- c(1, 5, 7, 9, 12)
country <- c("A", "A", "C", "E", "E")
price <- c(2.1, 4.6, 3.7, 2.9, 1.8)
quality <- c(3.1, 5.2, 3.3, 1.7, 0.9)
df1 <- cbind.data.frame(id, country, price, quality)

id <- c(2, 3, 4, 10, 14)
country <- c("F", "F", "A", "Z", "X")
price <- c(1.8, 5.2, 2.9, 4.6, 3.9)
quality <- c(4.3, 2.5, 6.9, 1.9, 0.8)
df2 <- cbind.data.frame(id, country, price, quality)

my.list <- list(df1, df2)

cols <- c("price", "quality")

这是我目前所拥有的,由于必要的手动更改,它仅适用于少数列:

my.list <- lapply(my.list, function(x) {
  x$price_w <- DescTools::Winsorize(x$price, probs = c(.01, .99), na.rm = TRUE)
  x$quality_w <- DescTools::Winsorize(x$quality, probs = c(.01, .99), na.rm = TRUE)
  return(x)
})

【问题讨论】:

    标签: r list function lapply


    【解决方案1】:

    这里有一个data.table 解决方案

    library( data.table )
    library( DescTools )
    #make df1 and df2 a data.table
    my.list <- lapply( my.list, setDT )
    #rund function on columns
    lapply( my.list, function(x) {
      x[, paste0( (cols), "_w" ) := DescTools::Winsorize( .SD, 
                                                          probs = c(0.1, 0.9), 
                                                          na.rm = TRUE ), .SDcols = cols]
    })
    
    # 
    # [[1]]
    #    id country price quality price_w quality_w
    # 1:  1       A   2.1     3.1     2.1      3.10
    # 2:  5       A   4.6     5.2     4.6      4.66
    # 3:  7       C   3.7     3.3     3.7      3.30
    # 4:  9       E   2.9     1.7     2.9      1.70
    # 5: 12       E   1.8     0.9     1.8      1.62
    # 
    # [[2]]
    #    id country price quality price_w quality_w
    # 1:  2       F   1.8     4.3     1.8      4.30
    # 2:  3       F   5.2     2.5     5.2      2.50
    # 3:  4       A   2.9     6.9     2.9      5.37
    # 4: 10       Z   4.6     1.9     4.6      1.90
    # 5: 14       X   3.9     0.8     3.9      1.70
    

    【讨论】:

      【解决方案2】:

      purrrdplyr 选项可以是:

      map(.x = my.list,
          ~ .x %>%
           mutate(across(all_of(cols), 
                         list(w = ~ DescTools::Winsorize(., probs = c(.01, .99), na.rm = TRUE)))))
      
      [[1]]
        id country price quality price_w quality_w
      1  1       A   2.1     3.1   2.100     3.100
      2  5       A   4.6     5.2   4.564     5.124
      3  7       C   3.7     3.3   3.700     3.300
      4  9       E   2.9     1.7   2.900     1.700
      5 12       E   1.8     0.9   1.812     0.932
      
      [[2]]
        id country price quality price_w quality_w
      1  2       F   1.8     4.3   1.844     4.300
      2  3       F   5.2     2.5   5.176     2.500
      3  4       A   2.9     6.9   2.900     6.796
      4 10       Z   4.6     1.9   4.600     1.900
      5 14       X   3.9     0.8   3.900     0.844
      

      【讨论】:

        【解决方案3】:

        我们可以使用嵌套的lapply 将函数应用于每个列表中的多个列。

        lapply(my.list, function(x) {
          x[paste0(cols, '_w')] <- lapply(x[cols], DescTools::Winsorize)
          x
        })
        
        #[[1]]
        #  id country price quality price_w quality_w
        #1  1       A   2.1     3.1    2.10      3.10
        #2  5       A   4.6     5.2    4.42      4.82
        #3  7       C   3.7     3.3    3.70      3.30
        #4  9       E   2.9     1.7    2.90      1.70
        #5 12       E   1.8     0.9    1.86      1.06
        
        #[[2]]
        #  id country price quality price_w quality_w
        #1  2       F   1.8     4.3    2.02      4.30
        #2  3       F   5.2     2.5    5.08      2.50
        #3  4       A   2.9     6.9    2.90      6.38
        #4 10       Z   4.6     1.9    4.60      1.90
        #5 14       X   3.9     0.8    3.90      1.02
        

        【讨论】:

        • 这工作得很好。但是,我有一个简短的问题。在 DescTools::Winsorize 中,我必须指定 x 和我想使用的相应概率。我是否必须初始化函数然后在嵌套的 lapply 中使用它,或者有没有办法输入正确的 x 因为 x 和 x[cols] 都不起作用?
        • 你可以像这样传递probs x[paste0(cols, '_w')] &lt;- lapply(x[cols], DescTools::Winsorize, probs = c(0.1, 0.9))
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-16
        • 1970-01-01
        • 2019-11-09
        • 1970-01-01
        相关资源
        最近更新 更多