【问题标题】:Separating positive and negative values in R data.table (many columns)在 R data.table 中分离正负值(多列)
【发布时间】:2022-01-05 09:12:05
【问题描述】:

我想知道如何通过 data.table 中的符号来拆分许多列。具体来说,假设我们有:

library(data.table)
DT = data.table(x = c(-1,-2,1,3),
                z = c(-1,-1,-1,-1))

我希望创建一个名为 DT_new 的新 data.table,它看起来像:


 DT_new
    x  z x_pos x_neg z_pos z_neg
1: -1 -1     0     1     0     1
2: -2 -1     0     2     0     1
3:  1 -1     1     0     0     1
4:  3 -1     3     0     0     1

我这样做的原因是我想在回归中分离出正变量和负变量。手动执行其中一些操作很容易。但是我有数百个变量想要应用这种技术。所以我希望有一个“SDcols”的解决方案。

谢谢!

【问题讨论】:

  • 是一个dplyr 解决方案作为替代接受或仅data.tabledplyr 在您的标签中。
  • 任何方法都可以,但最好是 data.table 解决方案。谢谢!

标签: r dplyr data.table magrittr


【解决方案1】:

无需使用 .SDcols ;-) 请在下面找到一个代表:

  • 代码
DT[,`:=` (x_pos = fifelse(x>0, x, 0),
          x_neg = fifelse(x<0, abs(x), 0),
          z_pos = fifelse(z>0, z, 0),
          z_neg = fifelse(z<0, abs(z), 0))][]
  • 输出
    x  z x_pos x_neg z_pos z_neg
1: -1 -1     0     1     0     1
2: -2 -1     0     2     0     1
3:  1 -1     1     0     0     1
4:  3 -1     3     0     0     1

作为您评论的后续行动

请在下面找到reprex。

  • 代码
vars <- c("x","z")
suffix <- c("_pos", "_neg")

DT[, CJ(vars, suffix, sorted = FALSE)[, paste0(vars, suffix)] := .(fifelse(x>0, x, 0),
                                                                   fifelse(x<0, abs(x), 0), 
                                                                   fifelse(z>0, z, 0),
                                                                   fifelse(z<0, abs(z), 0))][]
  • 输出
#>     x  z x_pos x_neg z_pos z_neg
#> 1: -1 -1     0     1     0     1
#> 2: -2 -1     0     2     0     1
#> 3:  1 -1     1     0     0     1
#> 4:  3 -1     3     0     0     1

reprex package (v2.0.1) 于 2021 年 11 月 28 日创建

【讨论】:

  • 谢谢!这很好用。但是如果我可能会问,有没有办法修改上面的代码来简单地输入一个向量 vars = c("x","z") 然后创建这些 _pos 和 _neg 列?原因是我需要对 100 个变量执行上述操作。谢谢!
  • 嗨@plausibly_exogenous,请在上方找到一个编辑来回答您的请求。干杯。
【解决方案2】:

我们可以将acrosscase_when 一起使用:

library(dplyr)
DT %>% 
  mutate(across(everything(), ~case_when(
    . < 0 ~ 0,
    TRUE ~ .), .names = "{col}_pos")) %>% 
  mutate(across(-contains("pos"), ~case_when(
    . < 0 ~ abs(.),
    TRUE ~ 0), .names = "{col}_neg"))
    x  z x_pos z_pos x_neg z_neg
1: -1 -1     0     0     1     1
2: -2 -1     0     0     2     1
3:  1 -1     1     0     0     1
4:  3 -1     3     0     0     1

【讨论】:

  • 这太棒了!谢谢!
【解决方案3】:

也许:

library(data.table)
DT = data.table(x = c(-1,-2,1,3),
                z = c(-1,-1,-1,-1))

col_nms <- c('x', 'z')
pos_nms <- paste0(col_nms, '_pos')
neg_nms <- paste0(col_nms, '_neg')

DT[, c(pos_nms) := lapply(.SD, function(.x) fifelse(.x > 0, .x, 0)), .SDcols = c('x', 'z')]
DT[, c(neg_nms) := lapply(.SD, function(.x) fifelse(.x < 0, -.x, 0)), .SDcols = c('x', 'z')]

DT
#>     x  z x_pos z_pos x_neg z_neg
#> 1: -1 -1     0     0     1     1
#> 2: -2 -1     0     0     2     1
#> 3:  1 -1     1     0     0     1
#> 4:  3 -1     3     0     0     1

reprex package (v2.0.1) 于 2021 年 11 月 27 日创建

【讨论】:

  • 谢谢!这很好用。但是如果我可能会问,有没有办法修改上面的代码来简单地输入一个向量vars = c("x","z"),然后创建这些_pos_neg 列?原因是我需要对 100 个变量执行上述操作。谢谢!
  • 我认为是的,名字有规律吗?例如,它们以相同的前缀开头?是 a-z 字母吗?
  • @plausibly_exogenous 我用初步解决方案编辑了代码。
  • 您的解决方案效果很好。非常感谢您的贡献。
【解决方案4】:
library(data.table)
DT = data.table(x = c(-1,-2,1,3),
                z = c(-1,-1,-1,-1))

vars <- names(DT)

DT <- DT[, sapply(.SD, function(j){
  list(ifelse(j<0, 0, j), 
       ifelse(j>0, 0, j))
})]

setnames(DT, paste(rep(vars, each=2), c("_pos", "_neg"), sep=""))

【讨论】:

    【解决方案5】:

    另一个 dplyr 选项

    library(data.table)
    library(dplyr, warn.conflicts = F)
    DT <- data.table(x = c(-1, -2, 1, 3),
                     z = c(-1, -1, -1, -1))
    
    DT %>%
      mutate(across(everything(), list(
        pos = ~ if_else(. > 0, ., 0),
        neg = ~ if_else(. < 0, -., 0)
      )))
    #>     x  z x_pos x_neg z_pos z_neg
    #> 1: -1 -1     0     1     0     1
    #> 2: -2 -1     0     2     0     1
    #> 3:  1 -1     1     0     0     1
    #> 4:  3 -1     3     0     0     1
    

    reprex package (v2.0.1) 于 2021 年 11 月 27 日创建

    如果您想使用此语法但在后台执行 data.table 操作,您可以使用tidytable

    library(data.table)
    library(tidytable, warn.conflicts = F)
    DT <- data.table(x = c(-1, -2, 1, 3),
                     z = c(-1, -1, -1, -1))
    
    DT %>%
      mutate.(across.(everything(), list(
        pos = ~ if_else(. > 0, ., 0),
        neg = ~ if_else(. < 0, -., 0)
      )))
    #> # A tidytable: 4 × 6
    #>       x     z x_pos x_neg z_pos z_neg
    #>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    #> 1    -1    -1     0     1     0     1
    #> 2    -2    -1     0     2     0     1
    #> 3     1    -1     1     0     0     1
    #> 4     3    -1     3     0     0     1
    

    reprex package (v2.0.1) 于 2021 年 11 月 27 日创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 2022-10-22
      • 2020-07-01
      相关资源
      最近更新 更多