【问题标题】:Use purrr::map to apply multiple arguments to a function使用 purrr::map 将多个参数应用于函数
【发布时间】:2017-07-19 23:30:03
【问题描述】:

我有一个这样的数据框

   df <- data.frame(tiny = rep(letters[1:3], 20), 
                  block = rnorm(60), tray = runif(60, min=0.4, max=2),
                  indent = sample(0.5:2.0, 60, replace = TRUE))

我嵌套了这个数据框

nm <- df%>%
       group_by(tiny)%>%
       nest()

然后写了这些函数

library(dplyr)
library(purrr)
library(tidyr)

model <- function(dfr, x, y){
             lm(y~x, data = dfr)
         }

model1 <- function(dfr){
           lm(block~tray, data = dfr)
          }

我想为所有小类运行这个模型,所以我做到了

 nm%>%
   mutate(
     mod = data %>% map(model1)
   )

上面的代码工作正常,但如果我想像在model1 函数中那样将变量作为参数提供,我会得到错误。这就是我的工作

 nm%>%
    mutate(mod = data %>% map(model(x=tray, y=block)))

我不断收到错误 Error in mode(x = tray, y = block) : unused argument (y = block)

我还尝试使用ggplot2 绘制这些图

plot <- function(dfr, i){
    dfr %>%
    ggplot(., aes(x=tray, y=block))+
geom_point()+
xlab("Soil Properties")+ylab("Slope Coefficient")+
ggtitle(nm$tiny[i])

nm%>%
 mutate(put = data %>% map(plot))

我的想法是,我希望 ggplot 为每个将要生成的图放置标题 abc产生。 任何帮助将不胜感激。谢谢

【问题讨论】:

  • 看起来不像 model1() 被定义为接受任何参数
  • @PierreLafortune,它没有用。我收到了错误Error: is.data.frame(.data) || is.list(.data) || is.environment(.data) is not TRUE
  • 有一天你们的孩子会停止尝试用管道传输所有内容

标签: r ggplot2 dplyr magrittr purrr


【解决方案1】:

如果您想将mutatemap 一起使用,您还需要将tidyrnest 一起使用。您将使用小标题来存储输出(或带有数据帧列表列的数据帧)。

我使用了@Sathish 详细答案中的函数(进行了一些修改)。

library(purrr)
library(dplyr)
library(tidyr) 

df <- data.frame(tiny = rep(letters[1:3], 20), 
                 block = rnorm(60), tray = runif(60, min=0.4, max=2),
                 indent = sample(0.5:2.0, 60, replace = TRUE))

lm_model <- function( data ) 
{
  return( lm( block ~ tray, data = data ) )
}

# Altered function to include title parameter with purrr::map2
plot_fun <- function( data, title )
{
  p <- ggplot( data = data, aes( x = tray, y = block ) ) +
    geom_point( ) +
    xlab("Soil Properties") + 
    ylab("Slope Coefficient") +
    ggtitle( as.character( title ) )

  return( p )
}


results <- df %>% 
  group_by(tiny) %>% 
  nest() %>% 
  mutate(model = map(data, lm_model),
         plot = map2(data, tiny, plot_fun))

你最终得到:

> results

# A tibble: 3 × 4
    tiny              data    model     plot
  <fctr>            <list>   <list>   <list>
1      a <tibble [20 × 3]> <S3: lm> <S3: gg>
2      b <tibble [20 × 3]> <S3: lm> <S3: gg>
3      c <tibble [20 × 3]> <S3: lm> <S3: gg>

您可以使用unnest 或通过提取([[[)访问您需要的内容

> results$model[[1]]

Call:
lm(formula = block ~ tray, data = data)

Coefficients:
(Intercept)         tray  
    -0.3461       0.3998  

【讨论】:

  • 我现在可以将标题添加到我的情节中。谢谢
【解决方案2】:

使用基本函数split 将数据拆分为组列表。

library( purrr )
library( ggplot2 )
df %>% 
  split( .$tiny) %>%
  map(~ lm( block ~ tray, data = .))

df %>% 
  split( .$tiny) %>%
  map(~ ggplot( data = ., aes( x = tray, y = block ) ) +
        geom_point( ) +
        xlab("Soil Properties") + 
        ylab("Slope Coefficient") +
        ggtitle( as.character( unique(.$tiny) ) ) )

使用函数:

lm_model <- function( data ) 
{
  return( lm( block ~ tray, data = data ) )
}

plot_fun <- function( data )
{
  p <- ggplot( data = data, aes( x = tray, y = block ) ) +
    geom_point( ) +
    xlab("Soil Properties") + 
    ylab("Slope Coefficient") +
    ggtitle( as.character( unique(data$tiny) ) )

  return( p )
}

df %>% 
  split( .$tiny) %>%
  map(~ lm_model( data = . ) )

df %>% 
  split( .$tiny) %>%
  map(~ plot_fun( data = . ) )

在函数内部创建公式

lm_model <- function( data, x, y ) 
{
  form <- reformulate( y, x )

  return( lm( formula = form, data = data ) )
}

df %>% 
  split( .$tiny) %>%
  map(~ lm_model( data = ., x = 'tray', y = 'block' ) )

如果您的函数如下所示,您的解决方案将会奏效。

model <- function(dfr, x, y){
  lm( formula = eval(parse(text = paste('as.formula( ', y, ' ~ ', x, ')', sep = ''))),
      data = dfr)
}

【讨论】:

  • 这就像我在问题中给出的模型示例。我开始学习另一种很棒的方法。但是,我希望能够使用函数并在 using map 中向函数提供我想要的任何参数。
  • 您确实回答了部分问题。在您的 lm_model 函数中,我可以更改 blocktray 并将它们作为函数中的参数提供吗?我该怎么做?
  • 是的。所以在这种情况下,我会将数据框、x 变量和y 变量传递给lm_model 函数并使用map 函数进行评估
  • 您的解决方案完美运行。我不明白为什么df%&gt;%group_by(tiny)%&gt;%mutate(mod = data %&gt;%map(lm_model(x='tray', y='block', data=.))) 不起作用。
  • lm_model 函数的第二行,输入print(form)。你会看到魔法。欲了解更多信息,请阅读?reformulate
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-20
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多