【问题标题】:How do I create a conditional variable based on another variable in R?如何基于 R 中的另一个变量创建条件变量?
【发布时间】:2021-07-18 14:52:58
【问题描述】:

在使用 SAS 几年后,我重新开始使用 R,并且我正在重新学习所有内容。

我有一个包含变量 Lot_Size 的数据集,其中包含 0.1980028 - 1.2000000 英亩的连续数据。我想根据这些分界线对这个变量进行分类:

0 - 1/3 英亩 = 0

1/3 - 2/3 英亩 = 1

2/3 - 1 英亩 = 2

1+ 英亩 = 3

放入一个新的变量LS_cat。

我已经探索了 mutate 命令,但我不断返回错误。有人有什么想法吗?

更新

感谢您的回复 - 两种解决方案都运行良好。由于这对我来说是一次学习经历,所以我将补充问题。

我实际上误解了向我提出的问题 - 如果我要为前面提到的每个类别制作虚拟变量,我会怎么做?例如,如果 Lot_Size 为 0 - 1/3 英亩,我希望变量 ls_1_3 为 1,如果不是,我希望它为 0。我会使用 ifelse 命令吗?

【问题讨论】:

    标签: r dummy-variable categorization


    【解决方案1】:

    使用case_when()

    library(tidyverse)
    
    set.seed(123)
    my_df <- tibble(
      lot_size = runif(n = 10, min = 0.1980028, max = 1.2)
    )
    
    
    my_df |> mutate(
      ls_cat = case_when(lot_size < 1 / 3 ~ 0, 
                         lot_size < 2 / 3 ~ 1, 
                         lot_size < 1 ~ 2, 
                         TRUE ~ 3)
    )
    
    #> A tibble: 10 x 2
    #>   lot_size ls_cat
    #>      <dbl>  <dbl>
    #> 1    0.486      1
    #> 2    0.988      2
    #> 3    0.608      1
    #> 4    1.08       3
    #> 5    1.14       3
    #> 6    0.244      0
    #> 7    0.727      2
    #> 8    1.09       3
    #> 9    0.751      2
    #>10    0.656      1
    

    【讨论】:

      【解决方案2】:

      Case_when() 在有两个以上选项时通常是一个合理的解决方案(if_else() 如果只有两个),但在这种情况下有一个更简单的数学解决方案。

      my_df <- tibble(lot_size = seq(0, 1.2, by = 0.1))
      my_df$ls_cat <-  ceiling((my_df$lot_size*3)-0.99)
      

      不过,这可能对 R 编程的指导意义不大。

      对于您的后续问题,ifelse() 效果很好,例如

      基地:

      my_df$ls_1_3 <- ifelse(my_df$lot_size < 1/3, 1, 0)
      

      或者 Tidyverse:

      my_df <- my_df %>% 
        mutate(ls_1_3 = if_else(lot_size < 1/3, 1, 0))
      

      注意:if_else()ifelse() 的更迂腐版本。两者在这里应该同样有效,但if_else() 更适合捕捉可能的错误

      【讨论】:

      • 后续as.numeric(my_df$lot_size &lt; 1/3) 也可以使用(效率更高,可读性稍差)
      • @r2evans,OP 的“后续”问题要求提供二进制输出。
      • 那么,+(my_df$log_size &lt; 1/3) 的可读性并没有降低很多,代码高尔夫球更小,但额外的好处是返回是integer,这对分类更有意义(在我看来)变量。
      【解决方案3】:

      我们可以使用findInterval:

      Lot_Size <- seq(0.2, 1.2, len=10)
      Lot_Size
      #  [1] 0.2000000 0.3111111 0.4222222 0.5333333 0.6444444 0.7555556 0.8666667 0.9777778 1.0888889 1.2000000
      findInterval(Lot_Size, c(0, 1/3, 2/3, 1, Inf), rightmost.closed = TRUE) - 1L
      #  [1] 0 0 1 1 1 2 2 2 3 3
      

      在这种情况下,它返回向量中的 索引,然后我们将其转换为基于 0 的结尾 - 1L(整数 1)。

      【讨论】:

        【解决方案4】:

        cut它。

        dat <- transform(dat, Lot_Size_cat=
                           cut(Lot_Size, breaks=c(0, 1/3, 2/3, 1, Inf), labels=0:3,
                               include.lowest=TRUE))
        dat
        #            X1  Lot_Size Lot_Size_cat
        # 1  0.77436849 1.0509024            3
        # 2  0.19722419 0.2819626            0
        # 3  0.97801384 0.8002238            2
        # 4  0.20132735 0.9272001            2
        # 5  0.36124443 0.6396998            1
        # 6  0.74261194 1.0990851            3
        # 7  0.97872844 1.1648617            3
        # 8  0.49811371 0.7221819            2
        # 9  0.01331584 1.1915689            3
        # 10 0.25994613 0.4076475            1
        

        数据:

        set.seed(666)
        n <- 10
        dat <- data.frame(X1=runif(n),
                          Lot_Size=sample(seq(0.1980028, 1.2, 1e-7), n, replace=TRUE))
        

        【讨论】:

          猜你喜欢
          • 2022-01-03
          • 2016-10-21
          • 2023-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多