在列表中有效地重复data.table,从循环中的另一个data.table顺序替换具有相同名称的列

问题描述 投票:1回答:1

我有两个data.tables:

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.tables它可能是低效的。我希望以data.table方式获得更多。我尝试了一些我认为会起作用的东西:

lapply(names(x), function(i) {
  y[ , (i) := x[ , i, with = FALSE]]
})

但是,它将第一个列表组件返回为空,并将x的所有值复制到下一个列表组件中。

有人可以帮忙吗?

r loops replace data.table updates
1个回答
3
投票

在这里,我们可能需要一个'y'的copy,同时创建list'w'而不是

w <- rep(list(y), ncol(y))

寻找rep的下面表达是很诱人的。但是,这在w元素中存在问题,因为它们指向内存中的相同位置

w <- rep(list(copy(x)), ncol(y))

通过引用赋值(:=)会更改每个循环中的列值,因为它们引用了内存中的同一对象。在第一种情况下,在赋值之后,它与'w'list元素一起改变'y'。第二种情况,它只能改变'w'并留下'y',因为我们用copyied。要了解行为,请在set循环中执行for赋值

for(j in seq_along(x)) {print(w[[j]][[j]])
        set(w[[j]], i = NULL, j =j, x[[j]])
        print("----")
        print(w[[j]])
   } 

为了避免这种情况,请使用qazxsw poi

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

如果我们在创建'w'时没有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 ied'y'对象,那么可以使用来自Map的简单base R来完成而不是通过引用进行赋值。

copy

© www.soinside.com 2019 - 2024. All rights reserved.