purrr 函数中的点对点机制

dot-dot-dot mechanism inside purrr functions

让我从玩具数据集开始

library(magrittr)
library(purrr)
set.seed(13)
X<-matrix(rnorm(120),20,6) %>% data.frame %>% set_colnames(LETTERS[1:5])

和一个绘制 6 个散点图的玩具函数:X 的每一列对应随机向量一个。

foo<-function(X){
  win.graph(5,5)
  par(mfcol=c(3,2))
  par(mar=c(5,4,.1,.1))
  X %>% iwalk(~plot(.x, rnorm(20), xlab=.y, ylab='Random'))
}

foo(X)

现在我给它加上点点点机制:

foo<-function(X,...){
  win.graph(5,5)
  par(mfcol=c(3,2))
  par(mar=c(5,4,.1,.1))
  X %>% iwalk(~plot(.x, rnorm(20), xlab=.y, ylab='Random',...))
}

现在 foo(X) 结果出现错误 Error in plot.window(...) : invalid 'xlim' valuefoo(X, pch=2) 也给出同样的错误。

这是为什么?为什么 iwalk 似乎将通过 ... 传递的任何附加参数放入 xlim?如何更改以上代码以便能够通过 ...?

传递附加参数

编辑

我用 quos 函数和 !!! 运算符尝试了 tidyeval 方法:

foo<-function(X, ...){
  win.graph(5,5)
  par(mfcol=c(3,2))
  par(mar=c(5,4,.1,.1))
  vars<-quos(...)
  X %>% iwalk(~plot(.x, rnorm(20),xlab=.y, ylab='Random', !!! vars))
}

现在 foo(X)foo(X, pch=2) 的结果都是 Error in plot.xy(xy, type, ...) : invalid plot type...

我们可以做到这一点 do.call

foo <- function(X, ...){
     v1 <- c(...)

  win.graph(5,5)
  par(mfcol=c(3,2))
  par(mar=c(5,4,.1,.1))
   X %>%
      iwalk(~ {args <- list(xlab = .y, ylab = 'Random')
               args[names(v1)] <- v1
           do.call(plot, c(list(x = .x, y = rnorm(20)), args))            

               }) 
  }

foo(X)
foo(X, cex = 2)
foo(X, pch = 2)
foo(X, cex = 2, pch = 2)
foo(X, cex = 2, pch = 2, col = 2)

给出输出