在R

时间:2018-09-05 20:12:43

标签: r nested-lists

我想为嵌套列表中具有相同名称的特定元素分配相同的值。如果嵌套列表中不存在该元素,我也想创建它,但是在我的示例中未显示。

例如,假设我有:

ls <- list(a = list(e1 = "value1.1", e2 = "value1.2"),
           b = list(e1 = "value2.1", e2 = "value2.2"))

我想为名为e1的子列表中的所有元素分配值“相同的值”,以便最终得到此所需的输出:

list(a = list(e1 = "same value", e2 = "value1.2"),
     b = list(e1 = "same value", e2 = "value2.2")
> ls
  $a
  $a$e1
  [1] "same value"

  $a$e2
  [1] "value1.2"


  $b
  $b$e1
  [1] "same value"

  $b$e2
  [1] "value2.2"

经过研究,我在软件包modify_depth()中发现了函数purrr,该函数会将函数应用于嵌套列表,但不会分配值。

我唯一的其他解决方案是执行此操作:

ls2 <- list()
for(sublist in ls){
  sublist[["e1"]] <- "same value"
  ls2 <- c(ls2, list(sublist))
}
names(ls2) <- names(ls)
ls <- ls2
rm(ls2)

注意:循环后,ls中未分配“相同的值”,因此我必须创建ls2。我可以使它成为一个函数,但是我敢肯定,没有for循环,还有更好的方法。

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

使用map中的replacepurrr

library(purrr)
map(ls, ~replace(., "e1", "same value"))

或使用modify_depth

modify_depth(ls, 1, ~replace(., "e1", "same value"))

replace也可以与lapply一起使用:

lapply(ls, replace, "e1", "same value")

输出:

$a
$a$e1
[1] "same value"

$a$e2
[1] "value1.2"


$b
$b$e1
[1] "same value"

$b$e2
[1] "value2.2"

modify_depth的优点是您可以选择深度,而maplapply只能下降一级:

ls2 <- list(c = list(a1 = list(e1 = "value1.1", e2 = "value1.2")),
            d = list(a1 = list(e1 = "value2.1", e2 = "value2.2")))

modify_depth(ls2, 2, ~replace(., "e1", "same value"))

输出:

$c
$c$a1
$c$a1$e1
[1] "same value"

$c$a1$e2
[1] "value1.2"


$d
$d$a1
$d$a1$e1
[1] "same value"

$d$a1$e2
[1] "value2.2"

编辑:如果我们要将值向量应用于e1的每个ls2元素,则modify_depth将不起作用,因为它没有map2个变体。相反,我将使用两层map,在顶层使用map2,在第二层使用map

vec <- c("newvalue1.1", "newvalue2.1")

map2(ls2, vec, ~map(.x, replace, "e1", .y))

输出:

$c
$c$a1
$c$a1$e1
[1] "newvalue1.1"

$c$a1$e2
[1] "value1.2"


$d
$d$a1
$d$a1$e1
[1] "newvalue2.1"

$d$a1$e2
[1] "value2.2"

答案 1 :(得分:1)

我们可以使用lapply遍历列表元素,然后将[与用于逻辑运算符的==等同使用> lapply(ls, function(x){ x[names(x)=="e1"] <- "same.value" x } ) $`a` $`a`$`e1` [1] "same.value" $`a`$e2 [1] "value1.2" $b $b$`e1` [1] "same.value" $b$e2 [1] "value2.2" ,我们可以找到我们想要更改的值

{{1}}

答案 2 :(得分:-1)

ls是R保留的,所以我建议使用其他名称作为列表,我的替代方法是:

y <- list(a = list(e1 = "value1.1", e2 = "value1.2"),
           b = list(e1 = "value2.1", e2 = "value2.2"))

lapply(y, function(x) replace(x, list = "e1", values = "new value"))

$a
$a$e1
[1] "new value"

$a$e2
[1] "value1.2"


$b
$b$e1
[1] "new value"

$b$e2
[1] "value2.2"