【问题标题】:Add each element of a vector as new column in data.table将向量的每个元素添加为 data.table 中的新列
【发布时间】:2021-11-17 20:29:35
【问题描述】:

如果一个向量有 5 个元素,我需要在我的data.table 中添加 5 列。 我的第一个新列的唯一值是我的向量的元素 1。

这是我可以用 for 做的事情,如下面的我的代表:

foo <- data.table(col1 = 1:10, col2 = sample(letters[1:5], replace = TRUE))

fun.add <- function(DT) {
  
  v1 <- c(3, 5.5, 9)
  v2 <- c("x", "y", "z")
  
  for (j in 1:3) {
    DT[, paste0("aaa", j) := v1[j]]
    DT[, paste0("bbb", j) := v2[j]]
  }
  
  # DT[, paste0("aaa", 1:3),  := ...]
}

fun.add(foo)

我宁愿在没有for 的情况下这样做,而更喜欢在评论行中。 在这种情况下,我不能使用lapply.SD ... 有办法吗?另一种方式?

谢谢!!

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    这是我的解决方案。

    输入:

    v1  <- c(3, 5.5, 9)
    v2  <- c("x", "y", "z")
    foo <- data.table(col1 = 1:10, col2 = sample(letters[1:5], replace = TRUE))
    
    N_col0 <- NCOL(foo) # used later on to redefine column class
    

    代码:

    v12 <- c(rbind(v1, v2))
    m12 <- matrix(rep(v12, each = NROW(foo)), NROW(foo))
    foo <- cbind(foo, m12)
    numeric_col <- grep("[0-9]", v12) + N_col0
    for(j in numer_col){set(foo, j=j, value=as.numeric(foo[[j]]))}
    

    代码解释:

    1.结合 v1 和 v2。

    v12 <- c(rbind(v1, v2)) # note it is a character vector
    
    print(v12)
    [1] "3"   "x"   "5.5" "y"   "9"   "z"  
    

    2.创建v12的字符矩阵。如果您愿意,可以在此阶段设置列名。

    m12 <- matrix(rep(v12, each = NROW(foo)), NROW(foo))
    
    print(v12)
          [,1] [,2] [,3]  [,4] [,5] [,6]
     [1,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [2,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [3,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [4,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [5,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [6,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [7,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [8,] "3"  "x"  "5.5" "y"  "9"  "z" 
     [9,] "3"  "x"  "5.5" "y"  "9"  "z" 
    [10,] "3"  "x"  "5.5" "y"  "9"  "z" 
    

    3.c绑定 foo & m12.

    foo<- cbind(foo, m12)
    
    print(foo)
        col1 col2 V1 V2  V3 V4 V5 V6
     1:    1    b  3  x 5.5  y  9  z
     2:    2    d  3  x 5.5  y  9  z
     3:    3    d  3  x 5.5  y  9  z
     4:    4    e  3  x 5.5  y  9  z
     5:    5    d  3  x 5.5  y  9  z
     6:    6    b  3  x 5.5  y  9  z
     7:    7    d  3  x 5.5  y  9  z
     8:    8    d  3  x 5.5  y  9  z
     9:    9    e  3  x 5.5  y  9  z
    10:   10    d  3  x 5.5  y  9  z
    

    4.所有新列都是字符列。为了解决这个问题,我们可以检测向量 12 中哪些元素是数字的,并使用数据表的函数集。

    foo[, lapply(.SD, class)]
    
          col1      col2        V1        V2        V3        V4        V5        V6
    1: integer character character character character character character character
    
    
    numeric_col <- grep("[0-9]", v12) + N_col0
    for(j in numer_col){set(foo, j=j, value=as.numeric(foo[[j]]))}
    
    foo[, lapply(.SD, class)]
    
      col1      col2      V1        V2      V3        V4      V5        V6
    1: integer character numeric character numeric character numeric character
    

    【讨论】:

    • 需要基准测试。不确定它是否比留在data.table 更有效。
    【解决方案2】:

    我们可以更有效地执行此操作,而不是在 for 循环中执行此操作,即将向量转换为带有 as.listlist 并通过分配 (:=) 到创建的列名向量来创建列with paste (paste 是矢量化的)

    foo[, paste0("aaa", seq_along(v1)) := as.list(v1)]
    foo[, paste0("bbb", seq_along(v2)) := as.list(v2)]
    

    如果我们把它包装在一个函数中

    fun.add <- function(DT) {
         v1 <- c(3, 5.5, 9)
         v2 <- c("x", "y", "z")
         DT[, paste0("aaa", seq_along(v1)) := as.list(v1)]
         DT[, paste0("bbb", seq_along(v2)) := as.list(v2)][]
        return(DT)
    }
    

    -测试

    > fun.add(foo)
        col1 col2 aaa1 aaa2 aaa3 bbb1 bbb2 bbb3
     1:    1    a    3  5.5    9    x    y    z
     2:    2    e    3  5.5    9    x    y    z
     3:    3    d    3  5.5    9    x    y    z
     4:    4    c    3  5.5    9    x    y    z
     5:    5    b    3  5.5    9    x    y    z
     6:    6    a    3  5.5    9    x    y    z
     7:    7    e    3  5.5    9    x    y    z
     8:    8    d    3  5.5    9    x    y    z
     9:    9    c    3  5.5    9    x    y    z
    10:   10    b    3  5.5    9    x    y    z
    

    【讨论】:

    • 秘密等待你的回答@akrun,来了!我喜欢使用paste0 来创建列,我忘记分配:= 需要list,虽然这是基本的...
    猜你喜欢
    • 2021-10-04
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多