使用 ggplot2 在 3 个子图中绘制时间序列数据的原始值、环比变化和同比变化

2024-04-29

给定两个每月时间序列数据样本.

我需要创建一个包含 3 个子图的图:plot1 表示原始值,plot2 表示逐月变化,plot3 表示逐年变化。

我可以用下面的代码绘制绘图,但是代码太冗余了。所以我的问题是如何以简洁的方式实现这一目标?谢谢。

library(xlsx)
library(ggplot2)
library(reshape)
library(dplyr)
library(tidyverse)
library(lubridate)
library(cowplot)
library(patchwork)

df <- read.xlsx('./sample_data.xlsx', 'Sheet1')
colnames(df)
# df

cols <- c('food_index', 'energy_index')
df <- df %>% mutate(date=as.Date(date)) %>% 
  mutate(across(-contains('date'), as.numeric)) %>% 
  mutate(date= floor_date(date, 'month')) %>%
  group_by(date) %>%
  summarise_at(vars(cols), funs(mean(., na.rm=TRUE))) %>%
  mutate(across(cols, list(yoy = ~(. - lag(., 12))/lag(., 12)))*100) %>%
  mutate(across(cols, list(mom = ~(. - lag(., 1))/lag(., 1)))*100) %>% 
  filter(date >= '2018-01-01' & date <= '2021-12-31') %>%
  as.data.frame()

df1 <- df %>%
  select(!grep('mom|yoy', names(df))) 

df1_long <- melt(df1, id.vars = 'date')
plot1 <- ggplot(df1_long[!is.na(df1_long$value), ],
       aes(x = date,
           y = value,
           col = variable)) +
  geom_line(size=0.6, alpha=0.5) +
  geom_point(size=1, alpha=0.8) +
  labs(
    x='',
    y='Unit: $'
  ) 

# MoM changes
df2 <- df %>%
  select(grep('date|mom', names(df)))

df2_long <- melt(df2, id.vars = 'date')
plot2 <- ggplot(df2_long[!is.na(df2_long$value), ],
       aes(x = date,
           y = value,
           col = variable)) +
  geom_line(size=0.6, alpha=0.5) +
  geom_point(size=1, alpha=0.8) +
  labs(
    x='',
    y='Unit: %'
  ) 

# YoY changes
df3 <- df %>%
  select(grep('date|yoy', names(df))) 

df3_long <- melt(df3, id.vars = 'date')
plot3 <- ggplot(df3_long[!is.na(df3_long$value), ],
       aes(x = date,
           y = value,
           col = variable)) +
  geom_line(size=0.6, alpha=0.5) +
  geom_point(size=1, alpha=0.8) +
  labs(
    x='',
    y='Unit: %'
  )
plot <- plot1 + plot2 + plot3 + plot_layout(ncol=1)
# plot <- plot_grid(plot1, plot2, plot3, labels = c('Value', 'MoM', 'YoY'), label_size = 12)
plot

Out:

预期结果将类似于下图(上图将显示原始数据,中图将显示环比变化数据,下图将显示同比变化数据):

参考:

https://waterdata.usgs.gov/blog/beyond-basic-plotting/ https://waterdata.usgs.gov/blog/beyond-basic-plotting/

http://www.sthda.com/english/articles/24-ggpubr-publication-ready-plots/81-ggplot2-easy-way-to-mix-multiple-graphs-on-the-same-page/ http://www.sthda.com/english/articles/24-ggpubr-publication-ready-plots/81-ggplot2-easy-way-to-mix-multiple-graphs-on-the-same-page/

使用 ggplot2 并排绘图 https://stackoverflow.com/questions/1249548/side-by-side-plots-with-ggplot2


也许这就是您正在寻找的?通过使用绘图函数将数据重塑为正确的形状,例如purrr::map2您可以实现您想要的结果,而无需像这样重复代码。

使用一些虚假的随机示例数据来模仿您的真实数据:

library(tidyr)
library(dplyr)
library(ggplot2)

df_long <- df |> 
  rename(food_index_raw = food_index, energy_index_raw = energy_index) |> 
  pivot_longer(-date, names_to = c("variable", ".value"), names_pattern = "^(.*?_index)_(.*)$")

plot_fun <- function(x, y, ylab) {
  x <- x |> 
    select(date, variable, value = .data[[y]]) |> 
    filter(!is.na(value))
  
  ggplot(
    x,
    aes(
      x = date,
      y = value,
      col = variable
    )
  ) +
    geom_line(size = 0.6, alpha = 0.5) +
    geom_point(size = 1, alpha = 0.8) +
    labs(
      x = "",
      y = ylab
    )  
}

yvars <- c("raw", "mom", "yoy")
ylabs <- paste0("Unit: ", c("$", "%", "%"))

plots <- purrr::map2(yvars, ylabs, plot_fun, x = df_long)

library(patchwork)

wrap_plots(plots) + plot_layout(ncol = 1)

DATA

set.seed(123)

date <- seq.POSIXt(as.POSIXct("2017-01-31"), as.POSIXct("2022-12-31"), by = "month")
food_index <- runif(length(date))
energy_index <- runif(length(date))

df <- data.frame(date, food_index, energy_index)

EDIT使用时为每个图添加字幕patchwork(目前)有点棘手。在这种情况下我要做的是使用分面“hack”。为此,我稍微调整了函数以获取字幕参数并切换到purrr::pmap:

library(tidyr)
library(dplyr)
library(ggplot2)

df_long <- df |> 
  rename(food_index_raw = food_index, energy_index_raw = energy_index) |> 
  pivot_longer(-date, names_to = c("variable", ".value"), names_pattern = "^(.*?_index)_(.*)$")

plot_fun <- function(x, y, ylab, subtitle) {
  x <- x |> 
    select(date, variable, value = .data[[y]]) |> 
    filter(!is.na(value))
  
  ggplot(
    x,
    aes(
      x = date,
      y = value,
      col = variable
    )
  ) +
    geom_line(size = 0.6, alpha = 0.5) +
    geom_point(size = 1, alpha = 0.8) +
    facet_wrap(~.env$subtitle) +
    labs(
      x = "",
      y = ylab
    ) +
    theme(strip.background = element_blank(), strip.text.x = element_text(hjust = 0))
}

yvars <- c("raw", "mom", "yoy")
ylabs <- paste0("Unit: ", c("$", "%", "%"))
subtitle <- c("Original", "Month-to-Month", "Year-to-Year")

plots <- purrr::pmap(list(y = yvars, ylab = ylabs, subtitle = subtitle), plot_fun, x = df_long)

library(patchwork)

wrap_plots(plots) + plot_layout(ncol = 1)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ggplot2 在 3 个子图中绘制时间序列数据的原始值、环比变化和同比变化 的相关文章

  • 将 r 数据框中的列字符串转换为数字

    我有一个数据框 其中有一列字符串 如下所示 mydata lt c 1 356670 35 355030 1 356670 35 355030 1 356620 35 355890 1 356930 35 358660 1 357000 3
  • 带有 geom_errorbar 的position_dodge

    我有以下代码 require ggplot2 pd lt position dodge 0 3 ggplot dt aes x Time y OR colour Group geom errorbar aes ymin CI lower y
  • r caret 包中的 train 函数的模型输出尺寸巨大

    我正在使用 bagFDA 模型进行训练train r caret 包中的函数 并将模型输出保存为 Rdata 文件 输入文件大约有 300k 条记录 有 26 个变量 但输出 Rdata 大小为 3G 我只是运行以下命令 modelout
  • 自定义 colorRampPalette 中的颜色条

    我定义了一个 colorRampPalette my colors colorRampPalette c light green yellow orange red 如何为其绘制颜色条 图例 项目 最好仅使用基本包 我正在寻找一个充满该颜色
  • R中的不定积分

    我正在计算方程的不定积分 我将加速度计的数据通过可视化 C 程序输入到 R 中 然后就可以很简单地得出一个方程来表示加速度曲线 这一切都很好 但是我还需要计算撞击速度 根据我在高中时代的理解 我的加速度曲线的不定积分将产生速度方程 我知道执
  • 根据另一个向量替换向量中的值

    我想替换向量中的值 x 与另一个向量 y 陷阱 22 方法需要是动态的 以适应向量中不同数量的 级别 x 例如 考虑向量x x lt sample c 1 2 3 4 5 100 replace TRUE gt x 1 2 4 1 1 3
  • 使用 RMySQL 会干扰 RPostgreSQL

    我有一个 R 脚本 我想从 MySQL 数据库中提取一些数据 然后从 PostgreSQL 数据库中提取一些数据 但是 从 RMySQL 加载 MySQL 驱动程序会阻止我从以下位置加载 PostgreSQL 驱动程序 PostgreSQL
  • 无重叠的抖动点

    My data a lt sample 1 5 100 replace TRUE b lt sample 1 5 100 replace TRUE c lt sample 1 10 100 replace TRUE d lt sample
  • 字边界正则表达式问题

    我在使用单词边界时遇到问题 b在我的正则表达式中 我正在使用 R 但当我尝试时问题也存在http regexr com http regexr com 我使用的模式是 bs l b 虽然我预计下面的第 1 行和第 3 行能够匹配此模式 但只
  • 使用 purrr::map() 更改和分配新变量名称

    我刚刚开始掌握编写函数并使用 lapply purrr map 使我的代码更加简洁 但显然还没有完全理解它 在我当前的示例中 我想重命名 lm robust 对象的系数名称 然后更改 lm robust 对象以合并新名称 我目前这样做 li
  • 列槽不足

    当尝试为 data table 中的每个变量 108 个变量 创建 12 个滞后时 我收到一条错误 指出列槽不足 此操作应创建大约 1200 个变量或列 Data A as data table Datos A Varnames names
  • 计算 R 中数据帧的每一行中特定值的连续出现次数

    我有一个data frame许多位置 这么多行 的变量的每月值 我想计算值为零的连续月份 即连续单元格 的数量 如果只是从左到右阅读 这很容易 但增加的复杂性是年底与年初是连续的 例如 在下面的缩短示例数据集中 用季节而不是月份 位置 1
  • 了解用于处理色边距的scale_fill_continuous_divergingx参数输入

    这个问题是我上一个问题的延续here https stackoverflow com questions 58718527 setting midpoint for continuous diverging color scale on a
  • 如何融合颜色和形状?

    当我有一个超过 6 个值的变量时 我的麻烦就开始了 因为这是 ggplot2 中 scale shape 函数的当前最大值 由于这个问题 我尝试使用另一个变量来解决这个问题 我只是将原始变量的长度包裹起来 这是我的示例代码 dataf lt
  • Plotly 绘图不会在 RMarkdown 文档的 for 循环内渲染

    我正在尝试动态构建一个需要运行循环的报告 并为每次迭代打印一些消息 表格和绘图 我可以让一切正常运转except为了情节 示例 rmd r echo FALSE results asis fig keep all message FALSE
  • 根据不平凡的标准有效合并两个数据帧

    正在接听这个问题 https stackoverflow com questions 18821862 data selection error 18823432 18823432昨晚 我花了一个小时试图找到一个没有增长的解决方案data
  • read.table 和 read.delim 函数之间的区别

    两者有什么区别read table and read delim R语言中的函数 当您不确定函数的作用时 除了阅读帮助页面之外 您还可以检查函数的实际代码 例如 输入read delim显示该函数包含以下代码 gt read delim f
  • 使用 R 从字符串中提取函数参数

    最好使用stringr包 我想创建一个函数extract 以字符串向量作为参数 vec lt c div span icon hospital user i18n t Enrolments or i18n t Paper a string
  • R lubridate:当地语言的工作日

    如何获取本地语言的工作日和月份 My code library lubridate data lt c 10 02 2015 11 03 2015 data lubri lt dmy data wday data lubri label T
  • Shiny可以识别用鼠标选择的文本(突出显示的文本)吗?

    我需要用户将文本片段分配给 Shiny 中的类别或 代码 基本上 我希望用户突出显示输出中的文本 在下面的示例中 来自table or text输出 然后按一个按钮 code 并将选定的文本分配给应用程序内的对象 在下面的应用程序中 所选文

随机推荐

  • 如何将 pymongo.cursor.Cursor 转换为字典?

    我正在使用 pymongo 查询一个区域内的所有项目 实际上是查询地图上一个区域内的所有场馆 我用了db command SON 在搜索球形区域之前 它可以返回一本字典 字典中有一个名为results其中包含场馆 现在我需要在一个正方形区域
  • 在 ReportLab 中向画布元素添加超链接的最简单方法是什么?

    我正在使用 ReportLab 使用 Python 制作 pdf 我想向画布添加一个形状 并让该形状充当超链接 使以下示例中的矩形链接到 google com 的最简单方法是什么 from reportlab pdfgen import c
  • 处理变量的范围:内部循环

    作为一名直接进入 Go 的 JS 开发者 如果长度超过commits不止一个 我没有太多时间来完成这件事 而且我搜索的时间比我希望的要长 关于如何重组它或让它发挥作用有什么想法吗 case github PushPayload push p
  • VSCode:activeTextEditor编码

    有什么方法可以在我的扩展代码中获取当前文档编码 位于底部栏中 就像是vscode window activeTextEditor encoding 这似乎不可能 由于几乎不可能证明是否定的 因此本答案的其余部分记录了我的探索内容 字符串 e
  • PhantomJS CPU(核心)受限吗?

    我开始做一些基于并行浏览器的测试 并想看看在达到 100 CPU 之前我可以在 EC2 大型机器上并行运行多少个浏览器 我正在使用 JMeter webdriver 插件来实际运行浏览器 对于 FireFox 实际上每个 CPU 核心有 1
  • 使用 Mongodb 和 Node.js 在一个页面中处理多个表单

    我的登录和注册表单都在同一页面上 我已经指定了两种不同的路由来发布数据 但是当我点击注册表单末尾的注册按钮时 它会保存登录表单输入 没有 我看了这个问题 多种表单 一张处理页面 https stackoverflow com questio
  • 在word文档的标题中添加图片时出现问题

    我正在Word文档的标题中添加图片 它显示图像的框架并显示 当前无法显示图像 如果我将文本添加到标题 它会显示文本 如果我在文档正文中添加图像 它也会显示图像 获取图像也是如此 它在标题上显示文本 但没有图像 我的支票快用完了 有人可以建议
  • iOS - Xcode 错误:由于系统完整性保护而无法附加到进程

    当我从 XCode 运行按钮运行应用程序共享扩展 然后尝试共享文件时 XCode 经常显示以下错误 有人知道是什么原因造成的吗 错误 由于系统完整性保护 无法附加到进程 系统完整性保护 SIP 又名无根 是 OS X 10 11 中的一项新
  • 巨大下拉列表的替代方案(24,000 多个项目)

    在我的管理部分中 当我编辑项目时 我必须将每个项目附加到父项目 我有超过 24 000 个父项目的列表 这些项目按字母顺序列在下拉列表 音乐艺术家列表 中 在下拉菜单中列出所有这些项目的编辑页面有 2MB 对于使用旧机器的人来说 它的速度非
  • 由尾随空格分隔的 Cobol 字符串

    WORKING STORAGE FIRST STRING PIC X 15 VALUE SPACES SECOND STRING PIC X 15 VALUE SPACES OUTPUT STRING PIC X 31 VALUE SPAC
  • Mac/iPhone:有没有一种方法可以在不使用 Objective-C 的情况下获取线程标识符?

    有没有一种方法可以获取当前正在运行的线程的任何类型的线程标识符 而无需借助 Objective C 的 NSThread 我正在改进我们的自定义调试跟踪系统以正确处理多个线程 对于跟踪输出的每一行 我想打印线程 ID 或线程名称 线程可以通
  • Hamcrest 与 MockMvc:检查键是否存在,但值可能为空

    我正在使用 MockMvc 进行一些测试 我想验证 JSON 响应的结构 具体来说 我想确保属性的键存在 并且值是某种类型或为 null keyToNull null This may be null or a String keyToSt
  • Play 2.0 应用程序的依赖关系管理

    我们小组对基于 JVM 的开发有些陌生 我们正在开发由许多其他库组成的应用程序 我们发现 Play 框架对于开发 Web 应用程序非常有吸引力 该框架很棒 但我们本地开发的库的依赖管理有点令人烦恼 我们正在使用 Play 2 0 的 RC2
  • (响应式)表格宽度不适合 ios safari 上 iframe 内的容器

    我在 iPhone 的 safari 上的 iframe 内渲染表格时遇到问题 这是示例 http jsfiddle net qb86ojms http jsfiddle net qb86ojms 如果您在桌面浏览器 较小的尺寸 或 and
  • Java:使用类型参数访问私有构造函数

    这是后续这个关于java私有构造函数的问题 https stackoverflow com questions 2599440 accessing the private constructor 假设我有以下课程 class Foo
  • IE toDataUrl() 安全错误

    我需要从画布上获取图片 因此我从 Amazon S3 获取图像 我在那里启用了跨源资源共享 CORS 并将 croseOrigin 属性 匿名 设置为 img 它适用于 Chrome 和FireFox 但在 IE 上 我通过调用 toDat
  • 为什么这段代码会抛出 InvalidOperationException?

    我认为我的代码应该使ViewBag test财产等于 No Match 但它会抛出一个InvalidOperationException 为什么是这样 string str Hello1 Hello Hello2 string anothe
  • 任务“:app:checkReleaseDuplicateClasses”执行失败。扑

    请找到以下文件 1 应用程序 构建 gradle def localProperties new Properties def localPropertiesFile rootProject file local properties if
  • 使用 Jest 模拟延迟() RxJS

    有没有简单的方法来嘲笑delay 例如 带有假时间的可观察对象中的 RxJS 方法 我有这个方法 register user return this checkLog user delay 500 flatMap 当我删除时delay 方法
  • 使用 ggplot2 在 3 个子图中绘制时间序列数据的原始值、环比变化和同比变化

    给定两个每月时间序列数据样本 我需要创建一个包含 3 个子图的图 plot1 表示原始值 plot2 表示逐月变化 plot3 表示逐年变化 我可以用下面的代码绘制绘图 但是代码太冗余了 所以我的问题是如何以简洁的方式实现这一目标 谢谢 l