在列表中有效地重复 data.table,在循环中依次替换另一个 data.table 中具有相同名称的列
Efficietly repeat data.table in a list, sequentially replacing columns with the same names from another data.table in a loop
我有两个data.table
:
x <- data.table(a = c(1, 2, 3, 4, 1), b = c(2, 3, 4, 1, 2), c = c(3, 4, 1, 2, 3))
y <- data.table(a = c(1, 0, 0, 0, 1), b = c(0, 1, 0, 0, 0), c = c(0, 0, 0, 0, 1))
我想要实现的是创建一个 y
的列表,其长度为其列数,其中每个下一列都被 x
中同一列的值替换。期望的结果应如下所示:
[[1]]
a b c
1: 1 0 0
2: 2 1 0
3: 3 0 0
4: 4 0 0
5: 1 0 1
[[2]]
a b c
1: 1 2 0
2: 0 3 0
3: 0 4 0
4: 0 1 0
5: 1 2 1
[[3]]
a b c
1: 1 0 3
2: 0 1 4
3: 0 0 1
4: 0 0 2
5: 1 0 3
我尝试了什么:
z <- lapply(names(x), function(i) {
x[ , i, with = FALSE]
})
w <- rep(list(y), ncol(y))
myfun <- function(obj1, obj2) {
cbind(obj1, obj2)
}
u <- Map(myfun, obj1 = z, obj2 = w)
u <- lapply(u, function(i) {
setcolorder(i[ , unique(names(i)), with = FALSE], names(x))
})
它给了我想要的结果,但是非常笨拙并且需要太多步骤,因此,对于较大的 data.table
s 它可能效率低下。我想以 data.table
的方式获得更多。我尝试了一些我认为可行的方法:
lapply(names(x), function(i) {
y[ , (i) := x[ , i, with = FALSE]]
})
但是,returns 第一个列表组件为空,并将 x
的所有值复制到下一个列表组件中。
有人可以帮忙吗?
在这里,我们可能需要 copy
的 'y' 而创建 list
'w' 而不是
w <- rep(list(y), ncol(y))
下面的表达式 rep
很诱人。但是,w
元素中存在问题,因为这些元素指向内存中的相同位置
w <- rep(list(copy(x)), ncol(y))
通过引用赋值 (:=
) 会更改每个循环中的列值,因为它们引用内存中的同一对象。在第一种情况下,在赋值之后,它也会随着 'w' list
元素一起更改 'y' 。第二种情况,它只能更改 'w' 并保留 'y' 因为我们 copy
ied。要了解行为,请在 for
循环
中执行 set
赋值
for(j in seq_along(x)) {print(w[[j]][[j]])
set(w[[j]], i = NULL, j =j, x[[j]])
print("----")
print(w[[j]])
}
为了避免这种情况,请使用 replicate
w <- replicate(ncol(y), copy(y), simplify = FALSE)
然后执行 for
循环(在重新创建对象后,因为值已从之前的 运行 中替换)
for(j in seq_along(x)) {print(w[[j]][[j]])
set(w[[j]], i = NULL, j =j, x[[j]])
print("----")
print(w[[j]])
}
或基于Map
的作业
Map(function(u, v) u[, (v) := x[[v]]][], w, names(x))
#[[1]]
# a b c
#1: 1 0 0
#2: 2 1 0
#3: 3 0 0
#4: 4 0 0
#5: 1 0 1
#[[2]]
# a b c
#1: 1 2 0
#2: 0 3 0
#3: 0 4 0
#4: 0 1 0
#5: 1 2 1
#[[3]]
# a b c
#1: 1 0 3
#2: 0 1 4
#3: 0 0 1
#4: 0 0 2
#5: 1 0 3
如果我们在创建 'w'
Map(function(u, v) {u[[v]] <- x[[v]]
u}, w, names(x))
我有两个data.table
:
x <- data.table(a = c(1, 2, 3, 4, 1), b = c(2, 3, 4, 1, 2), c = c(3, 4, 1, 2, 3))
y <- data.table(a = c(1, 0, 0, 0, 1), b = c(0, 1, 0, 0, 0), c = c(0, 0, 0, 0, 1))
我想要实现的是创建一个 y
的列表,其长度为其列数,其中每个下一列都被 x
中同一列的值替换。期望的结果应如下所示:
[[1]]
a b c
1: 1 0 0
2: 2 1 0
3: 3 0 0
4: 4 0 0
5: 1 0 1
[[2]]
a b c
1: 1 2 0
2: 0 3 0
3: 0 4 0
4: 0 1 0
5: 1 2 1
[[3]]
a b c
1: 1 0 3
2: 0 1 4
3: 0 0 1
4: 0 0 2
5: 1 0 3
我尝试了什么:
z <- lapply(names(x), function(i) {
x[ , i, with = FALSE]
})
w <- rep(list(y), ncol(y))
myfun <- function(obj1, obj2) {
cbind(obj1, obj2)
}
u <- Map(myfun, obj1 = z, obj2 = w)
u <- lapply(u, function(i) {
setcolorder(i[ , unique(names(i)), with = FALSE], names(x))
})
它给了我想要的结果,但是非常笨拙并且需要太多步骤,因此,对于较大的 data.table
s 它可能效率低下。我想以 data.table
的方式获得更多。我尝试了一些我认为可行的方法:
lapply(names(x), function(i) {
y[ , (i) := x[ , i, with = FALSE]]
})
但是,returns 第一个列表组件为空,并将 x
的所有值复制到下一个列表组件中。
有人可以帮忙吗?
在这里,我们可能需要 copy
的 'y' 而创建 list
'w' 而不是
w <- rep(list(y), ncol(y))
下面的表达式 rep
很诱人。但是,w
元素中存在问题,因为这些元素指向内存中的相同位置
w <- rep(list(copy(x)), ncol(y))
通过引用赋值 (:=
) 会更改每个循环中的列值,因为它们引用内存中的同一对象。在第一种情况下,在赋值之后,它也会随着 'w' list
元素一起更改 'y' 。第二种情况,它只能更改 'w' 并保留 'y' 因为我们 copy
ied。要了解行为,请在 for
循环
set
赋值
for(j in seq_along(x)) {print(w[[j]][[j]])
set(w[[j]], i = NULL, j =j, x[[j]])
print("----")
print(w[[j]])
}
为了避免这种情况,请使用 replicate
w <- replicate(ncol(y), copy(y), simplify = FALSE)
然后执行 for
循环(在重新创建对象后,因为值已从之前的 运行 中替换)
for(j in seq_along(x)) {print(w[[j]][[j]])
set(w[[j]], i = NULL, j =j, x[[j]])
print("----")
print(w[[j]])
}
或基于Map
的作业
Map(function(u, v) u[, (v) := x[[v]]][], w, names(x))
#[[1]]
# a b c
#1: 1 0 0
#2: 2 1 0
#3: 3 0 0
#4: 4 0 0
#5: 1 0 1
#[[2]]
# a b c
#1: 1 2 0
#2: 0 3 0
#3: 0 4 0
#4: 0 1 0
#5: 1 2 1
#[[3]]
# a b c
#1: 1 0 3
#2: 0 1 4
#3: 0 0 1
#4: 0 0 2
#5: 1 0 3
如果我们在创建 'w'
Map(function(u, v) {u[[v]] <- x[[v]]
u}, w, names(x))