我有一个清单list。此列表的前 5 个元素是:
[[1]]
[1] "#solarpanels" "#solar"
[[2]]
[1] "#Nuclear" "#Wind" "#solar"
[[3]]
[1] "#solar"
[[4]]
[1] "#steel" "#windenergy" "#solarenergy" "#carbonfootprint"
[[5]]
[1] "#solar" "#wind"
Run Code Online (Sandbox Code Playgroud)
我想删除元素,[[3]]因为只包含一个元素。此外,我想为列表的每一行构建一个包含所有可能组合的数据框。例如,具有两列(例如第一个 named A,第二个B)的数据框,例如:
A B
"#solarpanels" "#solar"
"#Nuclear" "#Wind"
"#Nuclear" "#solar"
"#steel" "#windenergy"
"#steel" "#solarenergy"
"#steel" "#carbonfootprint"
"#windenergy" "#carbonfootprint"
"#windenergy" "#solarenergy"
"#solarenergy" "#carbonfootprint"
"#solar" "#wind"
Run Code Online (Sandbox Code Playgroud)
我尝试过(仅针对一个元素)
for (i in 1:(length(list[[4]])-1)) {
df$from = rep(list[[4]][i],length(list[[4]])-i)
df$to = list[[4]][(i+1):length(list[[4]])]
}
Run Code Online (Sandbox Code Playgroud)
在哪里
df=data.frame(A=character(),
B=character(),
stringsAsFactors=FALSE)
Run Code Online (Sandbox Code Playgroud)
但我得到了
data.frame`(`*tmp*`, A, value = c("#steel", "#steel", :
replacement has 3 rows, data has 0
Run Code Online (Sandbox Code Playgroud)
为i=1。
你的数据第一:
l = list(
c("#solarpanels", "#solar"),
c("#Nuclear", "#Wind", "#solar"),
"#solar",
c("#steel", "#windenergy", "#solarenergy", "#carbonfootprint"),
c("#solar", "#wind")
)
Run Code Online (Sandbox Code Playgroud)
这是一个两行版本:
l = l[lengths(l) > 1L]
data.frame(do.call(rbind, unlist(lapply(l, combn, 2L, simplify = FALSE), recursive = FALSE)))
# X1 X2
# 1 #solarpanels #solar
# 2 #Nuclear #Wind
# 3 #Nuclear #solar
# 4 #Wind #solar
# 5 #steel #windenergy
# 6 #steel #solarenergy
# 7 #steel #carbonfootprint
# 8 #windenergy #solarenergy
# 9 #windenergy #carbonfootprint
# 10 #solarenergy #carbonfootprint
# 11 #solar #wind
Run Code Online (Sandbox Code Playgroud)
更慢,为了清楚起见:
combn(x, k)返回大小的每一个可能的(无序的)子集k从x; 你所追求的是来自列表中每个元素的对。默认情况下,它以matrix带p = choose(length(x), k)列的形式返回它,但这对您的用例来说不是一种有用的格式;simplify = FALSE将每个子集作为 a 的新元素返回list。
所以lapply(l, combn, 2L, simplify = FALSE)看起来像:
# [[1]]
# [[1]][[1]]
# [1] "#solarpanels" "#solar"
#
#
# [[2]]
# [[2]][[1]]
# [1] "#Nuclear" "#Wind"
#
# [[2]][[2]]
# [1] "#Nuclear" "#solar"
Run Code Online (Sandbox Code Playgroud)
(我们必须过滤lfirst的长度为 1 的元素,因为2从长度为 1 的对象中请求元素是错误的,因此是第一行)
这lapply(.)一点是您问题的症结所在;其余的只是将输出(已经包含所有正确数据)转换为一种data.frame格式。
首先,lapply输出是嵌套的——它list是lists的一个。list长度为 2 的向量更统一;unlist(., recusive=FALSE)通过取消嵌套列表的第一级来实现这一点(使用recursive=TRUE,我们会得到一个很大的长向量并失去配对结构;我们可以使用它,但我认为可能有点不自然)。
接下来,我们将长度为 2 的向量列表转换为矩阵(着眼于最终目标——2 列矩阵很容易转换为 a data.frame);list- >matrix在完成base与do.call(rbind, .)。
最后我们把它传给data.frame,等等!
在 中data.table,我会在一个命令中稍微清洁一点:
setDT(transpose(
unlist(lapply(l[lengths(l) > 1L], combn, 2L, simplify = FALSE), recursive = FALSE)
))[]
Run Code Online (Sandbox Code Playgroud)
鉴于您可能不太关心中间输出,这也是一个使用的好地方magrittr:
library(magrittr)
l[lengths(l) > 1L] %>%
lapply(combn, 2L, simplify = FALSE) %>%
unlist(recursive = FALSE) %>%
do.call(rbind, . ) %>%
data.frame
Run Code Online (Sandbox Code Playgroud)
它更具可读性,但在这种情况下,很高兴看到这data.frame是预先的最终目标,否则unlist&do.call步骤的意图可能会模糊不清。