【问题标题】:How to truncate multiple columns in R如何截断R中的多列
【发布时间】:2022-01-11 09:12:10
【问题描述】:

我需要截断许多列,使其范围从 -3.0 到 3.0。这意味着:任何大于 +3.0 的值都应重新编码为 +3.0 到一个新变量中,所有小于 -3.0 的值也应该重新编码到这个新变量中为 -3.0。

这是一个示例数据集

library(tidyverse)
MyData <- tibble( a = c(2.3, 3.0, -1.5, 3.7, -4.7, 5.2),
                  b = c(3.6, 1.52, -5.4, 4.6, 1.5, 2.2),
                  c = c(1.0, -2.6, -1.2, 2.5, -4.0, 3.0))

我发现了如何为每个旧变量创建一个新变量,使用 mutate()case_when() 但是我有太多变量无法手动完成,我想知道如何我可以用更短更优雅的方式来做到这一点。我希望看到类似于源自此手动代码的输出:

MyData %>% 
  mutate(Ta = case_when(a >= 3.0 ~ 3.0,
                        a <= -3.0 ~ -3.0,
                        T ~ a),
         Tb = case_when(b >= 3.0 ~ 3.0,
                        b <= -3.0 ~ -3.0,
                        T ~ b),
         Tc = case_when(c >= 3.0 ~ 3.0,
                        c <= -3.0 ~ -3.0,
                        T ~ c))

# A tibble: 6 x 6
      a     b     c    Ta    Tb    Tc
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1   2.3  3.6    1     2.3  3      1  
2   3    1.52  -2.6   3    1.52  -2.6
3  -1.5 -5.4   -1.2  -1.5 -3     -1.2
4   3.7  4.6    2.5   3    3      2.5
5  -4.7  1.5   -4    -3    1.5   -3  
6   5.2  2.2    3     3    2.2    3  

【问题讨论】:

    标签: r tidyverse case data-wrangling recode


    【解决方案1】:

    转换为矩阵,获取 pmin 和 pmax 并将其附加到 MyData。

    (虽然示例中不需要,但如果存在只应处理某些列的情况,则在 as.matrix 之前的管道中插入适当的 select 语句,例如 select(1:2) 或 select(a :b) 选择前两列或 select(where(is.numeric)) 仅选择数字列。)

    MyData %>%
      as.matrix %>%
      pmin(3) %>%
      pmax(-3) %>%
      cbind(MyData, T = .)
    

    给予:

         a     b    c  T.a   T.b  T.c
    1  2.3  3.60  1.0  2.3  3.00  1.0
    2  3.0  1.52 -2.6  3.0  1.52 -2.6
    3 -1.5 -5.40 -1.2 -1.5 -3.00 -1.2
    4  3.7  4.60  2.5  3.0  3.00  2.5
    5 -4.7  1.50 -4.0 -3.0  1.50 -3.0
    6  5.2  2.20  3.0  3.0  2.20  3.0
    

    【讨论】:

      【解决方案2】:

      您可以定义一个函数,然后使用across 将其应用于许多列。

      pmin(3, pmax(x, -3)) 是将向量(即数据框的一列)限制在 -3 到 3 范围内的一种方法。它取 x 和 -3 的最大值,然后取结果的最小值和 3 .

      across.names 参数让我们指定这些操作的结果应该是名为 T+[orig column name] 的附加列。

      cap3 <- function(x) { pmin(3, pmax(x, -3)) }
      
      MyData %>%
        mutate(across(a:c, cap3, .names = "T{.col}"))
      
        # mutate(across(1:3, cap3, .names = "T{.col}"))            # Equiv. alternative
        # mutate(across(everything(), cap3, .names = "T{.col}"))   # Equiv. alternative
      

      结果

      # A tibble: 6 x 6
            a     b     c    Ta    Tb    Tc
        <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
      1   2.3  3.6    1     2.3  3      1  
      2   3    1.52  -2.6   3    1.52  -2.6
      3  -1.5 -5.4   -1.2  -1.5 -3     -1.2
      4   3.7  4.6    2.5   3    3      2.5
      5  -4.7  1.5   -4    -3    1.5   -3  
      6   5.2  2.2    3     3    2.2    3  
      

      【讨论】:

        【解决方案3】:

        编写要应用于函数中每一列的代码,并使用across 应用它。

        library(dplyr)
        
        func <- function(a) {
          case_when(a >= 3.0 ~ 3.0,
                    a <= -3.0 ~ -3.0,
                    T ~ a)  
        }
        
        MyData %>%
          mutate(across(.fns = func, .names = 'T{col}'))
        
        #    a     b     c    Ta    Tb    Tc
        #  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
        #1   2.3  3.6    1     2.3  3      1  
        #2   3    1.52  -2.6   3    1.52  -2.6
        #3  -1.5 -5.4   -1.2  -1.5 -3     -1.2
        #4   3.7  4.6    2.5   3    3      2.5
        #5  -4.7  1.5   -4    -3    1.5   -3  
        #6   5.2  2.2    3     3    2.2    3  
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-04
          • 1970-01-01
          • 2018-10-27
          • 2021-01-28
          • 2020-06-05
          • 2017-09-20
          相关资源
          最近更新 更多