首页 > 解决方案 > 图表在函数之外创建,而不是在函数内部创建

问题描述

R 有点新,我想我可能误解了 R 中的函数是如何工作的。当我写这段代码时:

past_annual <- past_day %>% 
group_by(year) %>% 
summarize(annual_avg = mean(runoff_daily, na.rm = TRUE))

future_annual <- future_day %>% 
    group_by(year) %>% 
    summarize(annual_avg_45 = mean(runoff_daily_45, na.rm = TRUE),
              annual_avg_85 = mean(runoff_daily_85, na.rm = TRUE))

ggplot() +
    geom_line(data = past_annual, aes(x = year, y = annual_avg),
              color = "gray60") +
    geom_line(data = future_annual, aes(x = year, y = annual_avg_45),
              color = "turquoise4") +
    geom_line(data = future_annual, aes(x = year, y = annual_avg_85),
              color = "darkgoldenrod3") +
    theme_minimal()

它产生一个图runoff_graph

但是当我尝试将其写入函数时,它会产生一个空白图。

plot_annual = function(.y, .x, .z) {
  
  past_annual <- past_day %>% 
    group_by(year) %>% 
    summarize(annual_avg = mean(.y, na.rm = TRUE))
  
   future_annual <- future_day %>% 
    group_by(year) %>% 
    summarize(annual_avg_45 = mean(.x, na.rm = TRUE),
              annual_avg_85 = mean(.z, na.rm = TRUE))
  
  annual_graph <- ggplot() +
    geom_line(data = past_annual, 
              aes(x = year, y = annual_avg),
              color = "gray60") +
    geom_line(data = future_annual, 
              aes(x = year, y = annual_avg_45),
              color = "turquoise4") +
    geom_line(data = future_annual, 
              aes(x = year, y = annual_avg_85),
              color = "darkgoldenrod3") +
    theme_minimal()
  
  return(annual_graph)
}

plot_annual("runoff_daily", "runoff_daily_45", "runoff_daily_85")

函数图

我在这里想念什么?我直接从函数内部复制了代码并将变量替换为我想要的变量,所以我很困惑。另外,这是我的第一个堆栈溢出帖子,如果我错过了一些关键信息来回答我的问题,请道歉。

标签: r

解决方案


我认为问题更多在于您如何使用函数参数。考虑以下:

iris %>% 
  group_by(Species) %>% 
  summarize(avg_1 = mean(Sepal.Length),
            avg_2 = mean(Sepal.Width))

  Species    avg_1 avg_2
  <fct>      <dbl> <dbl>
1 setosa      5.01  3.43
2 versicolor  5.94  2.77
3 virginica   6.59  2.97

注意如何Sepal.LengthSepal.Width不在双引号内。这是基于如何dplyrtidyverse一般可以工作的特殊功能。

现在试试这个:

iris %>% 
  group_by(Species) %>% 
  summarize(avg_1 = mean("Sepal.Length"),
            avg_2 = mean("Sepal.Width"))

# A tibble: 3 x 3
  Species    avg_1 avg_2
  <fct>      <dbl> <dbl>
1 setosa        NA    NA
2 versicolor    NA    NA
3 virginica     NA    NA

Warning messages:
1: In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA
2: In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA
3: In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA
4: In mean.default("Sepal.Width") :
  argument is not numeric or logical: returning NA
5: In mean.default("Sepal.Width") :
  argument is not numeric or logical: returning NA
6: In mean.default("Sepal.Width") :
  argument is not numeric or logical: returning NA

不工作。这实际上就是您的功能正在做的事情。

f <- function(.x, .y) {
  iris %>% 
    group_by(Species) %>% 
    summarize(avg_1 = mean(.x),
              avg_2 = mean(.y))
}

f("Sepal.Length", "Sepal.Width")

# A tibble: 3 x 3
  Species    avg_1 avg_2
  <fct>      <dbl> <dbl>
1 setosa        NA    NA
2 versicolor    NA    NA
3 virginica     NA    NA

Warning messages:
1: In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA
2: In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA
3: In mean.default("Sepal.Length") :
  argument is not numeric or logical: returning NA
4: In mean.default("Sepal.Width") :
  argument is not numeric or logical: returning NA
5: In mean.default("Sepal.Width") :
  argument is not numeric or logical: returning NA
6: In mean.default("Sepal.Width") :
  argument is not numeric or logical: returning NA

解决这个问题实际上非常简单,但更高级一些。你可以在这里阅读一些关于它的内容,这将比我更好地解释它:https ://adv-r.hadley.nz/quasiquotation.html 。

但就目前而言,这应该是可行的。我无法重现您的示例,但您可以应用相同的概念。

f <- function(.x, .y) {
  .x <- rlang::ensym(.x)
  .y <- rlang::ensym(.y)
  
  iris %>% 
    group_by(Species) %>% 
    summarize(avg_1 = mean(!!.x),
              avg_2 = mean(!!.y))
}

f("Sepal.Length", "Sepal.Width")

# A tibble: 3 x 3
  Species    avg_1 avg_2
  <fct>      <dbl> <dbl>
1 setosa      5.01  3.43
2 versicolor  5.94  2.77
3 virginica   6.59  2.97

另一种选择是使用.data隐含在 中的代词dplyr

f <- function(.x, .y) {
  iris %>% 
    group_by(Species) %>% 
    summarize(avg_1 = mean(.data[[.x]]),
              avg_2 = mean(.data[[.y]]))
}

推荐阅读