【问题标题】:how to write a function that uses broom, dplyr and lm?如何编写一个使用 broom、dplyr 和 lm 的函数?
【发布时间】:2018-02-02 09:05:32
【问题描述】:

考虑这个非常简单的例子

library(dplyr)
library(broom)

dataframe <- data_frame(id = c(1,2,3,4,5,6),
                        group = c(1,1,1,2,2,2),
                        value = c(200,400,120,300,100,100))

# A tibble: 6 x 3
     id group value
  <dbl> <dbl> <dbl>
1     1     1   200
2     2     1   400
3     3     1   120
4     4     2   300
5     5     2   100
6     6     2   100

在这里,我想编写一个函数,输出value 平均值的置信估计上限。也就是说,

get_ci_high <- function(data, myvar){
  confint_tidy(lm(data = data, myvar ~ 1)) %>% pull(conf.high)
}

现在,这很容易实现

confint_tidy(lm(data = dataframe, value ~ 1)) %>% pull(conf.high)
[1] 332.9999

这也有效(注意group_by 之后的调用)

dataframe %>% group_by(group) %>% mutate(dealwithit = get_ci_high(., value))
# A tibble: 6 x 4
# Groups:   group [2]
     id group value dealwithit
  <dbl> <dbl> <dbl>      <dbl>
1     1     1   200   598.2674
2     2     1   400   598.2674
3     3     1   120   598.2674
4     4     2   300   453.5102
5     5     2   100   453.5102
6     6     2   100   453.5102

这很好用

mindblow <- function(data, groupvar, outputvar){
  quo_groupvar <- enquo(groupvar)
  quo_outputvar <- enquo(outputvar)

  data %>% group_by(!!quo_groupvar) %>% 
    summarize(output =  get_ci_high(., !!quo_outputvar))%>% 
    ungroup()

}

> mindblow(dataframe, groupvar = group, outputvar = value)
# A tibble: 2 x 2
  group   output
  <dbl>    <dbl>
1     1 598.2674
2     2 453.5102

...但这失败

get_ci_high(dataframe, value)
 Error in eval(expr, envir, enclos) : object 'value' not found 

我不明白这里有什么问题。我真的需要一个适用于上述四种情况的解决方案。

有什么想法吗? 非常感谢!!

【问题讨论】:

  • 试试get_ci_high(dataframe, dataframe$value)。
  • @meenaparam 这行不通,因为它不尊重group_by
  • @DavidRobinson group_by 参数是什么?
  • @meenaparam 哎呀,我的错。这在这种情况下会起作用;但我认为提问者正在寻找可以与 group_by 一起使用的东西,因为他们需要在公式中使用它
  • 啊哈,这是有道理的,感谢您编辑 Q。@DavidRobinson 击败了我,得到了答案、很好的解决方案和解释!

标签: r dplyr broom


【解决方案1】:

原因是当您传递value 参数时,您希望R 在公式中使用其名称 "value",而不是变量的值(不存在)。

一种解决方案是使用substitute() (non-standard evaluation) 提取名称,并使用as.formula 创建一个公式:

get_ci_high <- function(data, myvar) {
  col_name <- as.character(substitute(myvar))
  fmla <- as.formula(paste(col_name, "~ 1"))

  confint_tidy(lm(data = data, fmla)) %>% pull(conf.high)
}

get_ci_high(dataframe, value)

但是,我强烈建议将 公式 value ~ 1 作为第二个参数传递。这对于执行其他线性模型(当您也有预测器时)更简单、更灵活。

get_ci_high <- function(data, fmla) {      
  confint_tidy(lm(data = data, fmla)) %>% pull(conf.high)
}

get_ci_high(dataframe, value ~ 1)

【讨论】:

  • 非常好,谢谢大卫。可以肯定的是,公式是 R 解释不同于字符串或变量的东西,对吧?这就是它在这里工作的原因?
  • @ᴺᴼᴼᴮᴵᴱ 是的; R 保持公式不变,以后可以将其传递给其他函数,而不需要其中的变量立即存在(例如,试试a ~ b)。
  • argh... 问题是,您好的第一个解决方案不适用于更一般的设置。考虑这个函数mindblow &lt;- function(data, groupvar, outputvar){ quo_groupvar &lt;- enquo(groupvar) quo_outputvar &lt;- enquo(outputvar) df_agg &lt;- data %&gt;% group_by( !!quo_groupvar) %&gt;% summarize(output = get_ci_high(., !!quo_outputvar)) }你在这里看到一个简单的修复吗?
  • 为清晰起见对问题进行了编辑。我认为一个简单的解决方法是编写相同功能的两个版本。但这看起来效率太低了
  • 好的,让它与一些疯狂的 R 魔法一起工作。在mindblow 函数中使用get_ci_high(.,!!rlang::get_expr(quo_outputvar)))。我不确定为什么这会起作用:)
猜你喜欢
  • 2018-02-02
  • 1970-01-01
  • 2018-04-02
  • 2015-11-21
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多