繁体   English   中英

purrr 映射等效于嵌套 for 循环

[英]purrr map equivalent of nested for loop

purrr::map 相当于:

for (i in 1:4) {
  for (j in 1:6) {
    print(paste(i, j, sep = "-"))
  }
}

lapply(1:4, function(i) 
  lapply(1:6, function(j) 
    print(paste(i, j, sep = "-"))))

从概念上讲,我没有得到的是如何在内部map 函数中引用外部循环。

map(1:4, ~ map(1:6, ~ print(paste(.x, ????, sep = "-")))

尝试像这样嵌套时,函数公式 ( ~ ) 的使用会受到一些限制,因为完全不清楚您尝试引用的map级别。 (好吧,那是不正确的。我很清楚它引用的是inside-out ,并且由于它们都使用相同的命名法,因此外部变量被内部变量屏蔽了。)

我认为最好的解决方法是不使用公式方法,而是使用立即/匿名(或预定义)函数:

library(purrr)
str(map(1:2, function(x) map(1:3, function(y) paste(x, y, sep = "-"))))
# List of 2
#  $ :List of 3
#   ..$ : chr "1-1"
#   ..$ : chr "1-2"
#   ..$ : chr "1-3"
#  $ :List of 3
#   ..$ : chr "2-1"
#   ..$ : chr "2-2"
#   ..$ : chr "2-3"

正如@r2evans 指出的那样,您第一次调用的.x被屏蔽了。 但是,您可以创建一个带有 2 个参数.x.y的 lambda 函数,并通过...参数将之前的.x分配给新的.y

我将使用walk而不是map因为在这种情况下您只对副作用(打印)感兴趣

walk(1:4,~ walk(1:6, ~ print(paste(.x, .y, sep = "-")),.y=.x))

另一种选择是使用expand.grid来布置组合,然后使用pwalk (或其他情况下的pmap )迭代那些

purrr::pwalk(expand.grid(1:4,1:6),~print(paste(.x, .y, sep = "-")))

两种情况下的输出:

[1] "1-1"
[1] "2-1"
[1] "3-1"
[1] "4-1"
[1] "5-1"
[1] "6-1"
[1] "1-2"
[1] "2-2"
[1] "3-2"
[1] "4-2"
[1] "5-2"
[1] "6-2"
[1] "1-3"
[1] "2-3"
[1] "3-3"
[1] "4-3"
[1] "5-3"
[1] "6-3"
[1] "1-4"
[1] "2-4"
[1] "3-4"
[1] "4-4"
[1] "5-4"
[1] "6-4"

现在只是跑过这个。

walk(1:4,~ walk(1:6, ~ print(paste(.x, .y, sep = "-")),.y=.x)) 
[1] "1-1"
[1] "2-1"
[1] "3-1"
[1] "4-1"
[1] "5-1"
[1] "6-1"
[1] "1-2"

purrr::pwalk(expand.grid(1:4,1:6),~print(paste(.x, .y, sep = "-")))
[1] "1-1"
[1] "2-1"
[1] "3-1"
[1] "4-1"
[1] "1-2"

但是为了匹配你嵌套的 for 循环,它完全被摆弄了,这是有效的。

for (i in 1:4) {
  for (j in 1:6) {
    print(paste(i, j, sep = "-"))
  }
}
[1] "1-1"
[1] "1-2"
[1] "1-3"
[1] "1-4"
[1] "1-5"
[1] "1-6"
[1] "2-1"

purrr::pwalk(expand.grid(1:6,1:4),~print(paste(.y, .x, sep = "-")))
[1] "1-1"
[1] "1-2"
[1] "1-3"
[1] "1-4"
[1] "1-5"
[1] "1-6"
[1] "2-1"

#or even a map of this
walk(1:4,~ walk(1:6, ~ print(paste(.y, .x, sep = "-")),.y=.x))

我还没有弄清楚为什么.y=.x在最后。

这是对已经非常好的答案和答案评论的补充。 我想制作一个类似 purr 的功能来实现 OP 的目标。 所以我做了一个loop_map函数,它的行为类似于主要的 Purrr map函数。

loop_map <- function(why, ecks, fun) {
  
  # 2: for every call of this (the previous .f) the new .f is called for each
  # value of ecks, supplied the same value of why each time
  iterate_over_x = function(x_in,y_in,fun_in){
    return(pmap(.l = list(x = x_in), .f = fun_in ,y = y_in ) %>%
 set_names(nm = as.character(x_in))) 
  }
  
  # 1: this ".f"  argument is called once for each element of why, and is 
  # supplied one value of why and every value of ecks each time
  pmap(.l = list(y_in = why), .f = iterate_over_x, x_in = ecks, fun_in = fun) %>% 
set_names(nm = as.character(why))
  
}



my_paste <- function(x,y) {
  paste(x,y)
}



loop_map(list("a","b"),list("c","d"),my_paste)

作为奖励,我为输出命名,以便人们可以更轻松地对其进行索引,或者以某种方式将其转换为数据帧。 我想通过添加循环遍历任意多个输入列表的功能来改进此功能,并可能使用带有...参数的函数(现在所有内容都必须命名)。 如果有人对如何做到这一点有任何想法,请随时告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM