在自定义函数中使用for循环创建ggplot时间序列图

3
我正在尝试创建一个带有for循环的函数,该函数接受数据框中的列并根据列名创建不同的图形。我已经阅读了多个相关的SO问题,例如: 1创建使用ggplot2的循环函数[2]:在ggplot中循环变量 但是到目前为止没有什么效果。 样本数据:
philly_df_new <- structure(list(DATE = structure(c(14610, 14611, 14612, 14613, 
14614, 14615, 14616, 14617, 14618, 14619, 14620, 14621, 14622, 
14623, 14624, 14625, 14626, 14627, 14628, 14629), class = "Date"), 
    HOURLYDewPointTempC = c(0, -8.9, -15, -12.2, -11.7, -10.6, 
    -8.3, -4.4, -12.2, -17.2, -12.8, -6.1, -10.6, -7.8, -5.6, 
    -2.2, 0.6, 3.9, 0.6, -3.3), HOURLYSeaLevelPressure = c(30, 
    29.79, 29.78, 29.76, 29.81, 29.78, 29.89, 29.87, 29.98, 30.25, 
    30.27, 30.13, 30.22, 30.23, 30.21, 30.23, 30.14, 29.49, 29.95, 
    29.92), DAILYDeptFromNormalAverageTemp = c(-1.7, 2.4, -6.4, 
    -10.3, -6.2, -5.1, -1, -1, -5.9, -10.8, -11.8, -9.7, -3.7, 
    -1.7, -1.6, 4.4, 4.4, 6.4, 8.4, 4.3)), .Names = c("DATE", 
"HOURLYDewPointTempC", "HOURLYSeaLevelPressure", "DAILYDeptFromNormalAverageTemp"
), row.names = c(NA, -20L), class = c("tbl_df", "tbl", "data.frame"
))

我尝试的不同代码:

Plot_Graph<-function(x,na.rm=T){
  nm=names(x)
  for (i in seq_along(nm)) {
    print(ggplot(x,aes_string(x="DATE",y=i) +
            geom_point()))
                                      }
  }

Plot_Graph(philly_df_new)
colNames <- names(philly_df_new)[2:4]
for(i in seq_along(colNames)){
  plt <- ggplot(philly_df_new, aes_string(x="DATE", y = i)) +
    geom_point(color="#B20000", size=3, alpha=0.5,na.rm = T) 
  print(plt)
}

当我运行第一个函数时,我会得到以下错误信息:Error: Mapping should be created withaes()oraes_()。当我运行第二个函数时,我会得到一张相同的图表,重复出现并带有一条水平线。我尝试了更多的方法,但为了简化,我只展示这两种方法。我想要创建每列的时间序列图,就像这样:enter image description here

你所说的“什么都没有显示”是指什么?Rstudio 的绘图窗口中根本没有任何图形吗?Rstudio 一次只能显示一个图形。你只看到了最后一个图形吗?你是否收到任何错误消息?你使用的 ggplot2 版本是什么? - MrFlick
@MrFlick 不好意思,我没有想要如此模糊。我会更好地编辑问题。谢谢。 - NBE
@MrFlick 希望我的编辑使它更清晰。 - NBE
2
Plot_Graph 函数内,你的括号放错位置了。应该是 print(ggplot(x,aes_string(x="DATE",y=i))+geom_point()) - MrFlick
2个回答

3
以下内容有效。
您正在循环遍历所有列,包括列"DATE",这应该是x轴,而循环变量是整数,因此在绘图的美学中,y = i是一个整数,而不是列名。
请注意,我调用windows()打开一个新的图形窗口。如果不需要,请删除此操作。
Plot_Graph <- function(DF, na.rm = TRUE){
  nm = names(DF)[-1]
  for (i in nm) {
    g <- ggplot(DF, aes(x = DATE, y = get(i))) +
            geom_point()
    windows()
    print(g)
  }
}

Plot_Graph(philly_df_new)

我该如何添加一个Y标签?我尝试了“+ylab(get(i))”,但它会抛出一个错误!提前致谢! - SamV
1
请尝试使用 ylab(i),因为 i 已经是列名。 - Rui Barradas
请注意,windows仅适用于Windows操作系统。如果您使用其他操作系统,则可以使用X11()quartz() - Rui Barradas
实际上,我在iOS上使用它非常顺利 - 我正在导出这些内容,并不太关心弹出窗口 - 但是在Rstudio绘图控制台中也运行良好。最近妥协很流行;) ...... 哦,也许这真的是XQ或Homebrew的问题。 - SamV
以下是代码,希望能帮到其他人:Plot_Graph <- function(DF, na.rm = TRUE){ nm = names(DF)[-1] for (i in nm) { g <- ggplot(DF, aes(x = Date.Time, y = get(i))) + geom_point(na.rm=TRUE, size=0.5) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) + scale_x_datetime(breaks = "6 months", labels = date_format("%b %Y")) + xlab("日期") + ylab(i) print(g) ggsave(filename = sprintf('%s.png', i), plot = g) } }Plot_Graph(nf)
- SamV
@ Rui Barradas,有没有办法在单个面板中使用上面的代码进行面板图绘制?再次感谢! - SamV

1

使用 tidyeval 方法的解决方案,类似于 这个答案,需要 ggplot2 v3.0.0

  • 首先,我们构建一个函数,以 x- 和 y- 列作为输入。注意使用了 rlang::symrlang::quo_name!!

  • 然后,我们可以使用 purrr::map 循环遍历每一列。

library(rlang)
library(tidyverse)

philly_df_new <- structure(list(DATE = structure(c(14610, 14611, 14612, 14613, 
    14614, 14615, 14616, 14617, 14618, 14619, 14620, 14621, 14622, 
    14623, 14624, 14625, 14626, 14627, 14628, 14629), class = "Date"), 
        HOURLYDewPointTempC = c(0, -8.9, -15, -12.2, -11.7, -10.6, 
        -8.3, -4.4, -12.2, -17.2, -12.8, -6.1, -10.6, -7.8, -5.6, 
        -2.2, 0.6, 3.9, 0.6, -3.3), HOURLYSeaLevelPressure = c(30, 
        29.79, 29.78, 29.76, 29.81, 29.78, 29.89, 29.87, 29.98, 30.25, 
        30.27, 30.13, 30.22, 30.23, 30.21, 30.23, 30.14, 29.49, 29.95, 
        29.92), DAILYDeptFromNormalAverageTemp = c(-1.7, 2.4, -6.4, 
        -10.3, -6.2, -5.1, -1, -1, -5.9, -10.8, -11.8, -9.7, -3.7, 
        -1.7, -1.6, 4.4, 4.4, 6.4, 8.4, 4.3)), .Names = c("DATE", 
    "HOURLYDewPointTempC", "HOURLYSeaLevelPressure", "DAILYDeptFromNormalAverageTemp"
    ), row.names = c(NA, -20L), class = c("tbl_df", "tbl", "data.frame"
    ))

# define a function that accept strings as input
Plot_Graph <- function(df, x_var, y_var) {

  # convert strings to variable
  x_var <- rlang::sym(x_var)
  y_var <- rlang::sym(y_var)

  # unquote variable using !! 
  ggplot(df, aes(x = !! x_var, y = !! y_var)) + 
    geom_point() + 
    geom_line() +
    labs(x = rlang::quo_name(x_var), y = rlang::quo_name(y_var)) +
    scale_x_date(breaks = scales::pretty_breaks()) +
    theme_classic(base_size = 12)
}

现在循环遍历每一列。
plot_list <- colnames(philly_df_new)[-1] %>% 
  map( ~ Plot_Graph(philly_df_new, "DATE", .x))

plot_list
#> [[1]]

#> 
#> [[2]]

#> 
#> [[3]]

# Combine all plots
library(cowplot)

do.call(plot_grid, c(plot_list, 
                     align = "v",
                     axis = 'lr',
                     nrow = 3))

这段文字是由reprex包(v0.2.0.9000)于2018年8月27日创建的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接