【问题标题】:Calling a list index within a loop using names()使用 names() 在循环中调用列表索引
【发布时间】:2018-01-15 13:35:37
【问题描述】:

我有一个列表aa,它引用了另一个列表bb 的索引名称并包含另一个元素(称为cm)。列出 bb 项目包含字符串。我有一个循环通过bb,并且对于与我指定的字符串匹配的每个项目,将其添加到数据框中的新行中。我还需要将cm 值添加到该行。

例子:

library("tidyverse")

aa <- list(c(123, 1), c(234, 1), c(345, 2), c(456, 3))
bb <- list("123" = c("a", "b", "c"), "234" = c("b", "c", "d"), "345" = c("c", "d", "e"), "456" = c("f", "g", "h"))
cc <- c("a", "b", "c")

tbl <- NULL
for (a in aa){
  for (b in bb) {
      if (any(cc %in% b)) {
        tb <- tibble(cm=a[2],n1=b[1],n2=b[2],n3=b[3])
        tbl <- bind_rows(tbl,tb)
      }
    }
  }

这会遍历bb 的每个可能组合,并将其添加到每个cm 的配对中,这并不好。我的输出应该是这样的:

output <- tibble(cm = c(1, 1, 2), n1 = c("a", "b", "c"),
             n2 = c("b", "c", "d"), n3 = c("c", "d", "e"))

> output
# A tibble: 3 x 4
         cm    n1    n2    n3
      <dbl> <chr> <chr> <chr>
1         1     a     b     c
2         1     b     c     d
3         2     c     d     e

我认为这样的事情可能会起作用,因为至少我可以稍后循环通过 tbl 并使用 nm 将其替换为适当的 cm 值:

tbl <- NULL
for (a in aa){
  for (b in bb) {
    if (any(cc %in% b)) {
      tb <- tibble(nm = names(bb)[b], n1=b[1],n2=b[2],n3=b[3])
      tbl <- bind_rows(tbl,tb)
      }
     }
    }

我真的不明白为什么这不起作用,因为names(bb)[1] 返回123,所以我认为它与names(bb)[b] 在循环中会起作用。

【问题讨论】:

  • 你的 for 循环 for (b in bb) 循环遍历 bb 的每个元素,但是如果你想索引向量 names(bb) 你需要将循环写成 for (b in 1:length(bb)) 然后使用整数 b 索引列表 bb 和向量 names(bb)

标签: r list loops


【解决方案1】:

如果您对没有显式循环的基本 R 解决方案感到满意,这可行吗?

# generate data
aa <- list(c(123, 1), c(234, 1), c(345, 2), c(456, 3))
# cm is an element of bb
bb <- list("123" = c("a", "b", "c"), "234" = c("b", "c", "d"),
           "345" = c("c", "d", "e"), "456" = c("f", "g", "h"),
           cm = c(1, 1, 2))
cc <- c("a", "b", "c")

tbl <- data.frame(
  bb[["cm"]],
  # apply to each element of aa
  do.call(rbind, lapply(aa, function(x, y, c) { # function takes 3 args
    # only elements of bb whose names are in aa[[x]]
    names_y <- as.character(intersect(x, names(y)))
    # turn subset of bb into data.frame
    out <- as.data.frame(do.call(rbind, y[names_y]))
    # subset rows for which any row element %in% cc
    out <- out[apply(out, 1, function(x, c) any(x %in% c), c)] 
    return(out)
  }, bb, cc))) # pass bb and cc as args to the function in lapply()
names(tbl) <- c("cm", paste0("n", 1:(ncol(tbl) - 1)))

给予

 > tbl
    cm n1 n2 n3
123  1  a  b  c
234  1  b  c  d
345  2  c  d  e

【讨论】:

  • 谢谢!两个问题:1)cm=c(1,1,2) 添加到bb 是作弊。真正的aa 有 100-1000 件物品,所以我基本上是瞎了眼。另外,只需要提取cc 中指定的值就可以排除例如只是循环aa 来制作你的cm 向量,因为项目456 会导致错误:arguments imply differing number of rows: 4, 32) 真正的bb也是100个项目,它的索引以12等开头,所以names_y会从aa拉取任何项目names(bb)相交带有cm 值。我真的想不出办法解决这个问题......
  • 既然你想将cm添加到结果data.frame中,它必须支持length(cm) == nrow(tbl),所以cm在哪里并不重要:它可以在@987654341里面@、aa,或者只是在全球环境中漂浮。我不认为我理解其他问题,你能澄清一下吗?我不确定列表的长度有多重要?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多