将向量的每个元素添加为 data.table 中的新列
Add each element of a vector as new column in data.table
如果一个向量有 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
...
有办法吗?另一种方式?
谢谢!!
这是我的解决方案。
输入:
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.Combine v1 & v2.
v12 <- c(rbind(v1, v2)) # note it is a character vector
print(v12)
[1] "3" "x" "5.5" "y" "9" "z"
2.Create一个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.cBind 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.All 新列是字符列。为了解决这个问题,我们可以检测向量 12 中的哪些元素是数字,并使用数据函数集 table.
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
我们可以更有效地执行此操作,而不是在 for
循环中执行此操作,即将向量转换为具有 as.list
的 list
并通过分配创建列(:=
) 到使用 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
如果一个向量有 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
...
有办法吗?另一种方式?
谢谢!!
这是我的解决方案。
输入:
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.Combine v1 & v2.
v12 <- c(rbind(v1, v2)) # note it is a character vector
print(v12)
[1] "3" "x" "5.5" "y" "9" "z"
2.Create一个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.cBind 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.All 新列是字符列。为了解决这个问题,我们可以检测向量 12 中的哪些元素是数字,并使用数据函数集 table.
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
我们可以更有效地执行此操作,而不是在 for
循环中执行此操作,即将向量转换为具有 as.list
的 list
并通过分配创建列(:=
) 到使用 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