将列表粘贴到矢量,为每个矢量级别重复列表
Paste a list to a vector, repeating the list for each vector level
我想完成以下任务而不必进入 for
循环,而是在单个 apply()
命令中。
我有一个列表 a
,我想重复 N
次,其中 N
是向量 b
的长度,粘贴 [=13] 的每个重复=] 到 b
.
的元素
到目前为止,我已经完成了以下 MWE:
var <- paste("var", 1:4, sep="")
treat <- c("A","B")
spec <- paste("sp", 1:3, sep="")
a <- combn(var, 2, simplify = FALSE)#this 6 times, for each treatment and species
b <- do.call(paste, c(expand.grid(treat, spec), sep='.'))
a1 <- lapply(a, paste, b[1], sep='.')
a2 <- lapply(a, paste, b[2], sep='.')
a3 <- lapply(a, paste, b[3], sep='.')
a4 <- lapply(a, paste, b[4], sep='.')
a5 <- lapply(a, paste, b[5], sep='.')
a6 <- lapply(a, paste, b[6], sep='.')
a.final <- c(a1,a2,a3,a4,a5,a6)
a.final
如果我能在a
之前粘贴b
就更好了。
请注意,我的起点是 3 个向量:var
、treat
和 spec
,因此请随意更改从那一点开始的任何内容。
选项 1: 我们完全可以在没有任何 apply()
循环的情况下完成此操作。让我们 unlist()
a
列表,paste()
它到复制的 b
值,然后 relist()
它基于复制的 a
列表。试试这个:
aa <- relist(
paste(unlist(a), rep(b, each=sum(lengths(a))), sep="."),
rep.int(a, length(b))
)
检查:
identical(aa, a.final)
# [1] TRUE
Option 1 with b
before a
: 现在,要将 b
值放在前面,只需交换参数paste()
致电:
relist(
paste(rep(b, each=sum(lengths(a))), unlist(a), sep = "."),
rep.int(a, length(b))
)
选项 2: 此选项确实使用 apply()
循环。这里我们使用Map()
来做一对一的粘贴。
ra <- rep(a, length(b))
aa2 <- Map(paste, ra, relist(rep(b, each=sum(lengths(a))), ra), sep = ".")
检查:
identical(aa2, a.final)
# [1] TRUE
选项 2 在 a
之前带有 b
: 只需交换传递给 paste()
的未命名的 Map()
参数。
ra <- rep(a, length(b))
Map(paste, relist(rep(b, each=sum(lengths(a))), ra), ra, sep = ".")
接近 OP 的方法,这可以通过使用匿名函数的嵌套 lapply()
来解决:
unlist(lapply(b, function(x) lapply(a, function(y) paste(x, y, sep = "."))),
recursive = FALSE)
[[1]]
[1] "A.sp1.var1" "A.sp1.var2"
[[2]]
[1] "A.sp1.var1" "A.sp1.var3"
[[3]]
[1] "A.sp1.var1" "A.sp1.var4"
...
[[34]]
[1] "B.sp3.var2" "B.sp3.var3"
[[35]]
[1] "B.sp3.var2" "B.sp3.var4"
[[36]]
[1] "B.sp3.var3" "B.sp3.var4"
注意,b
是粘贴在a
前面的。 unlist()
需要展开顶级列表。
验证方法是否有效(b
前面的 a
与 a.final
进行比较):
identical(a.final,
unlist(lapply(b, function(x) lapply(a, function(y) paste(y, x, sep = "."))),
recursive = FALSE))
[1] TRUE
这是一种完全不同的方法,它从头开始创建标签并returns它们在 36 行 x 2 列中 data.table 而不是包含 36 个长度为 2 的向量的列表:
library(data.table)
# cross join of treat, spec, var. Note, full labels will be created in sprintf() below
DT <- CJ(LETTERS[1:2], 1:3, 1:4)
# non equi join as replacement of combn()
DT[DT, on = .(V1, V2, V3 > V3), nomatch = 0L,
# create labels
.(sprintf("%s.sp%s.var%i", V1, V2, V3),
sprintf("%s.sp%s.var%i", V1, V2, x.V3))]
V1 V2
1: A.sp1.var1 A.sp1.var2
2: A.sp1.var1 A.sp1.var3
3: A.sp1.var1 A.sp1.var4
4: A.sp1.var2 A.sp1.var3
5: A.sp1.var2 A.sp1.var4
6: A.sp1.var3 A.sp1.var4
7: A.sp2.var1 A.sp2.var2
...
29: B.sp2.var2 B.sp2.var4
30: B.sp2.var3 B.sp2.var4
31: B.sp3.var1 B.sp3.var2
32: B.sp3.var1 B.sp3.var3
33: B.sp3.var1 B.sp3.var4
34: B.sp3.var2 B.sp3.var3
35: B.sp3.var2 B.sp3.var4
36: B.sp3.var3 B.sp3.var4
V1 V2
我想完成以下任务而不必进入 for
循环,而是在单个 apply()
命令中。
我有一个列表 a
,我想重复 N
次,其中 N
是向量 b
的长度,粘贴 [=13] 的每个重复=] 到 b
.
到目前为止,我已经完成了以下 MWE:
var <- paste("var", 1:4, sep="")
treat <- c("A","B")
spec <- paste("sp", 1:3, sep="")
a <- combn(var, 2, simplify = FALSE)#this 6 times, for each treatment and species
b <- do.call(paste, c(expand.grid(treat, spec), sep='.'))
a1 <- lapply(a, paste, b[1], sep='.')
a2 <- lapply(a, paste, b[2], sep='.')
a3 <- lapply(a, paste, b[3], sep='.')
a4 <- lapply(a, paste, b[4], sep='.')
a5 <- lapply(a, paste, b[5], sep='.')
a6 <- lapply(a, paste, b[6], sep='.')
a.final <- c(a1,a2,a3,a4,a5,a6)
a.final
如果我能在a
之前粘贴b
就更好了。
请注意,我的起点是 3 个向量:var
、treat
和 spec
,因此请随意更改从那一点开始的任何内容。
选项 1: 我们完全可以在没有任何 apply()
循环的情况下完成此操作。让我们 unlist()
a
列表,paste()
它到复制的 b
值,然后 relist()
它基于复制的 a
列表。试试这个:
aa <- relist(
paste(unlist(a), rep(b, each=sum(lengths(a))), sep="."),
rep.int(a, length(b))
)
检查:
identical(aa, a.final)
# [1] TRUE
Option 1 with b
before a
: 现在,要将 b
值放在前面,只需交换参数paste()
致电:
relist(
paste(rep(b, each=sum(lengths(a))), unlist(a), sep = "."),
rep.int(a, length(b))
)
选项 2: 此选项确实使用 apply()
循环。这里我们使用Map()
来做一对一的粘贴。
ra <- rep(a, length(b))
aa2 <- Map(paste, ra, relist(rep(b, each=sum(lengths(a))), ra), sep = ".")
检查:
identical(aa2, a.final)
# [1] TRUE
选项 2 在 a
之前带有 b
: 只需交换传递给 paste()
的未命名的 Map()
参数。
ra <- rep(a, length(b))
Map(paste, relist(rep(b, each=sum(lengths(a))), ra), ra, sep = ".")
接近 OP 的方法,这可以通过使用匿名函数的嵌套 lapply()
来解决:
unlist(lapply(b, function(x) lapply(a, function(y) paste(x, y, sep = "."))),
recursive = FALSE)
[[1]] [1] "A.sp1.var1" "A.sp1.var2" [[2]] [1] "A.sp1.var1" "A.sp1.var3" [[3]] [1] "A.sp1.var1" "A.sp1.var4" ... [[34]] [1] "B.sp3.var2" "B.sp3.var3" [[35]] [1] "B.sp3.var2" "B.sp3.var4" [[36]] [1] "B.sp3.var3" "B.sp3.var4"
注意,b
是粘贴在a
前面的。 unlist()
需要展开顶级列表。
验证方法是否有效(b
前面的 a
与 a.final
进行比较):
identical(a.final,
unlist(lapply(b, function(x) lapply(a, function(y) paste(y, x, sep = "."))),
recursive = FALSE))
[1] TRUE
这是一种完全不同的方法,它从头开始创建标签并returns它们在 36 行 x 2 列中 data.table 而不是包含 36 个长度为 2 的向量的列表:
library(data.table)
# cross join of treat, spec, var. Note, full labels will be created in sprintf() below
DT <- CJ(LETTERS[1:2], 1:3, 1:4)
# non equi join as replacement of combn()
DT[DT, on = .(V1, V2, V3 > V3), nomatch = 0L,
# create labels
.(sprintf("%s.sp%s.var%i", V1, V2, V3),
sprintf("%s.sp%s.var%i", V1, V2, x.V3))]
V1 V2 1: A.sp1.var1 A.sp1.var2 2: A.sp1.var1 A.sp1.var3 3: A.sp1.var1 A.sp1.var4 4: A.sp1.var2 A.sp1.var3 5: A.sp1.var2 A.sp1.var4 6: A.sp1.var3 A.sp1.var4 7: A.sp2.var1 A.sp2.var2 ... 29: B.sp2.var2 B.sp2.var4 30: B.sp2.var3 B.sp2.var4 31: B.sp3.var1 B.sp3.var2 32: B.sp3.var1 B.sp3.var3 33: B.sp3.var1 B.sp3.var4 34: B.sp3.var2 B.sp3.var3 35: B.sp3.var2 B.sp3.var4 36: B.sp3.var3 B.sp3.var4 V1 V2