【问题标题】:Subset data to contain only columns whose names match multiple condition using data.table使用 data.table 子集数据以仅包含名称与多个条件匹配的列
【发布时间】:2022-08-19 15:37:47
【问题描述】:

这是基于此question。问题说:

有没有办法让我根据列名开始子集数据 有一个特定的字符串?我有一些类似于 ABC_1 的列 ABC_2 ABC_3 和一些像 XYZ _1、XYZ _2、XYZ _3 比方说。

如何仅根据包含上述内容的列对我的 df 进行子集化 部分文本(比如说,ABC 或 XYZ)?我可以使用索引,但是 列在数据中太分散了,变得太难了 编码。

另外,我只想包含这些列中的任何行 它们的值大于 0,因此如果上面 6 列中的任何一列有 1 in 行,它切入我的最终数据框。

使用 dplyr 选择的答案之一多列对于新数据:

df <- df %>% dplyr:: select(grep(\"ABC\", names(df)), grep(\"XYZ\", 名称(df)))

但是,我想要一个类似于上述的 data.table 解决方案。我知道(根据答案之一) data.table 可以做一个条件,但不确定如何做多个:

df[, grep(\"ABC\", names(df)), with = FALSE]

    标签: r data.table subset


    【解决方案1】:

    您可以在 data.table 中使用 patterns 在其 .SDcols 参数中选择与某些模式匹配的多个列:

    # turn df into data.table
    setDT(df)
    
    # select columns that contain ABD or XYZ
    df[, .SD, .SDcols=patterns("ABC|XYZ")]
    
    # or
    df[, grep("ABC|XYZ", names(df)), with=FALSE]
    

    同时对行和列进行子集化

    cols = grep("ABC|XYZ",  names(df))
    
    df[rowSums(df[, ..cols]>0)>0, .SD, .SDcols=cols]
    

    【讨论】:

      【解决方案2】:

      为什么不是这个?

      set.seed(1)
      df <- data.frame( ABC_1 = sample(0:1,3,repl = TRUE),
                        ABC_2 = sample(0:1,3,repl = TRUE),
                        XYZ_1 = sample(0:1,3,repl = TRUE),
                        XYZ_2 = sample(0:1,3,repl = TRUE),
                        BCD_1 = sample(0:1, 3, replace = TRUE))
      library(data.table)
      
      df[, c(grep("ABC", names(df)), grep("XYZ", names(df)))]
      #>   ABC_1 ABC_2 XYZ_1 XYZ_2
      #> 1     0     0     0     1
      #> 2     1     1     0     0
      #> 3     0     0     1     0
      

      创建于 2022-07-08 由 reprex package (v2.0.1)

      【讨论】:

      • 小细节,但您可以缩短最后一行:df[, c(grep("ABC|XYZ", names(df)))]
      【解决方案3】:

      假设您有一个data.table,其中包含这么多列:

      library(data.table)
      
      DF <- matrix(data = rnorm(n = 50), nrow = 5, ncol = 10) |> 
        round(digits = 2) |> 
        as.data.table()
      
      colnames(DF) <- paste0(letters[1:5], 1:10)
      DF
      #>       a1    b2    c3   d4    e5    a6    b7   c8    d9   e10
      #> 1:  0.50  0.23  1.59 1.77  1.14  0.54  1.43 0.77 -1.22  1.25
      #> 2:  0.16 -0.66  0.91 0.21 -2.96 -0.76  0.26 0.28 -0.59  0.23
      #> 3: -1.60 -1.01 -0.22 1.14 -1.94 -0.65 -0.36 0.94  0.31  0.47
      #> 4: -1.50  0.26 -0.54 0.60 -0.81 -0.41  0.30 0.52  0.10 -1.02
      #> 5: -0.60 -1.64  1.33 0.31 -1.82 -0.33 -1.89 0.34 -0.68  0.72
      
      

      要仅选择以某个前缀开头的列,例如“a”,您可以使用startsWith()

      DF[, .SD, .SDcols = startsWith(x = colnames(DF), prefix = "a")]
      #>       a1    a6
      #> 1:  0.50  0.54
      #> 2:  0.16 -0.76
      #> 3: -1.60 -0.65
      #> 4: -1.50 -0.41
      #> 5: -0.60 -0.33
      

      选择名称包含某些字符串的所有列,例如。无论是“a”还是“b”,您都可以将grep() 与匹配“a”或“b”的模式一起使用:

      DF[, .SD, .SDcols = grep(pattern = "a|b", x = colnames(DF))]
      #>       a1    b2    a6    b7
      #> 1:  0.50  0.23  0.54  1.43
      #> 2:  0.16 -0.66 -0.76  0.26
      #> 3: -1.60 -1.01 -0.65 -0.36
      #> 4: -1.50  0.26 -0.41  0.30
      #> 5: -0.60 -1.64 -0.33 -1.89
      

      【讨论】:

        【解决方案4】:

        data.table 的单行代码(使用 objectclosure 的示例 DF):

        DF[, .SD[rowSums(.SD > 0) > 0,], .SDcols = patterns("^a")]
        #       a1    a6
        #    <num> <num>
        # 1:  1.37 -0.70
        # 2:  1.92  0.60
        # 3:  0.41 -0.06
        # 4: -1.43  1.28
        # 5:  0.22 -0.89
        

        为清楚起见,因为代码中有两个 &gt; 0s:

        • .SD &gt; 0 是您的“超过 0 的值”的过滤器;和
        • rowSums(.) &gt; 0 表示一行中的一个或多个值满足上述条件。

        翻译,如果您想要一个或多个值大于 3 的行,那么内部代码将是 .SD[rowSums(.SD &gt; 3) &gt; 0,]

        【讨论】:

          猜你喜欢
          • 2013-09-06
          • 1970-01-01
          • 1970-01-01
          • 2019-05-15
          • 2021-01-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-07
          相关资源
          最近更新 更多