【问题标题】:How to plot missing dates in time series data using ggplot2?如何使用 ggplot2 绘制时间序列数据中缺失的日期?
【发布时间】:2020-03-28 06:12:56
【问题描述】:

我有一个缺少日期的温度时间序列数据(平均值、最大值、最小值),并且线图没有继续,该图使用水平线跳跃,直到下一个日期。我希望这条线继续。

我的数据集是下一个

Fecha      -- T      Tmin Tmax

1. Fecha      ---------- T   --   Tmin Tmax
2. 2015-07-01   - 11,16 - 7,3 -  17 
3. 2015-07-02    - 11,49 -   8   - 17,1
4. 2015-07-03   - 11,2 -    8,8 -     15,8
5. 2015-07-04 - 11,20 - 8,6  - 16
6. 2015-07-05    -11,23 -   8,9  - 15,7
7. 2015-07-06    -10,40  - 7,7  -  15,4
8. 2015-07-07 - 10,10 - 8,1 -  14,8
9. 2015-07-08 - 10,04 - 7,3 -  15,4
10. 2018-01-01   - 11,08 -  4,9 -  17,8
11. 2018-01-02   -11,40 -   4,2 -  16,3
12. 2018-01-03 -    9,000 - 5,5  - 13,5
13. 2018-01-04  - 8,584  - 6    -  12,8
14. 2018-01-05  - 8,679  - 7,3  -  11,9
15. 2018-01-06 -    8,75 -  6,8 -  13
16. 2018-01-07   - 9,33 - 6,4    - 15,2
17. 2018-01-08  - 9,63 -    6,3 -  13,9

我的代码是:

setwd("C:/Users/2018/Documents/Belmira")
dir()
mmp1<-read.csv2("Temperatura.csv")
head(mmp1)
p<-as.Date(mmp1$Fecha)
mmp1$Fecha<-p
w<-ggplot() +
  geom_line(mapping = aes(x = mmp1$Fecha, y = mmp1$Tmin, colour="Min"), size=0.71) +
  geom_line(mapping = aes(x = mmp1$Fecha, y = mmp1$T, colour="P"), size=0.71) +
  geom_line(mapping = aes(x = mmp1$Fecha, y = mmp1$Tmax, colour="Max"), size=0.71) +
  ylim(c(1,18))+
  theme (text = element_text(size=11)) +
  ylab(expression("Temperatura (°C)"))+
  xlab(expression("Tiempo"))+
  scale_x_date(labels = date_format("%d/%m"))+
  theme(axis.text.x=element_text(angle=45, hjust=1))+
  scale_x_date(date_breaks = "30 day", date_labels = "%m-%y", limits = as.Date(c('2015-07-01','2019-01-01')), expand = (c(0.001,0.008)))+
  theme(plot.title = element_text(hjust = 0.5))+
  theme(panel.background = element_rect(fill = 'white', colour = 'white', size = 1.2, linetype = 7))+
  theme(text=element_text(family="arial", face="bold", size=12))+
  theme(axis.title.y = element_text(face="bold", family = "arial", vjust=1.5, colour="black", hjust = 0.5, size=rel(1.2)))+
  theme(axis.title.x = element_text(face="bold", family = "arial", vjust=0.5, colour="black", size=rel(1.2)))+
  theme(axis.text.x = element_text(family= "arial",face = "plain", colour="black", size=rel(1.1)))+
  theme(axis.text.y = element_text(family= "arial",face = "plain", colour="black", size=rel(1.1)))+
  theme(axis.line = element_line(size = 1, colour = "black"))+
  scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(-4,28), expand=c(0,0))+
  scale_colour_manual(name="Leyenda",
                      values=c(Min="green", P="#56B4E9", Max="Red"))+
  theme(legend.title = element_text(colour="black", size=12, face="bold", family = "arial"))+
  theme(legend.key = element_rect(fill = "white"))+
  guides(colour=guide_legend(order = 2),
         shape=guide_legend(order = 2))
w

结果是:

【问题讨论】:

  • 欢迎来到 SO。请参阅@stefan 的回答以了解如何发布数据。最好是使用内置数据集。 R中有很多,对于时间序列,例如AirPassengers
  • 也看看我对 Stefan 的回答的评论 - 这主要是为了让你学习!希望这会有所帮助

标签: r ggplot2 time-series missing-data


【解决方案1】:

如果我说得对,您是否希望数据中的空白不显示为“长水平”线?这不是一个简单的任务。也许首选和最简单的解决方案是使用刻面,例如按年。如果您坚持将所有数据都放在一个图中,那么您必须尝试一种 hacky 方法,即去掉日期轴并手动设置标签。看看不同的方法:

df <- read.table(text="
    Fecha - T - Tmin - Tmax
    2015-07-01 - 11,16 - 7,3 - 17
    2015-07-02 - 11,49 - 8 - 17,1
    2015-07-03 - 11,2 - 8,8 - 15,8
    2015-07-04 - 11,20 - 8,6 - 16
    2015-07-05 - 11,23 - 8,9 - 15,7
    2015-07-06 - 10,40 - 7,7 - 15,4
    2015-07-07 - 10,10 - 8,1 - 14,8
    2015-07-08 - 10,04 - 7,3 - 15,4
    2018-01-01 - 11,08 - 4,9 - 17,8
    2018-01-02 - 11,40 - 4,2 - 16,3
    2018-01-03 - 9,000 - 5,5 - 13,5
    2018-01-04 - 8,584 - 6 - 12,8
    2018-01-05 - 8,679 - 7,3 - 11,9
    2018-01-06 - 8,75 - 6,8 - 13
    2018-01-07 - 9,33 - 6,4 - 15,2
    2018-01-08 - 9,63 - 6,3 - 13,9
", header = TRUE, dec = ",")

mmp1 <- df[,!grepl("^X", names(df))]
mmp1$Fecha <- as.Date(mmp1$Fecha)

library(ggplot2)
library(scales)
library(dplyr)
library(tibble)

mmp2 <- mmp1 %>% 
  mutate(
    year_fecha = as.character(lubridate::year(Fecha)),
    Fecha2 = format(Fecha, "%d-%m"),
    Fecha2 = forcats::fct_reorder(Fecha2, Fecha)) %>% 
  arrange(Fecha) %>% 
  rowid_to_column(var = "Fecha3")

# Put the theme code aside
polish <- theme(text = element_text(size=11)) +
  theme(axis.text.x=element_text(angle=45, hjust=1))+
  theme(plot.title = element_text(hjust = 0.5))+
  theme(panel.background = element_rect(fill = 'white', colour = 'white', size = 1.2, linetype = 7))+
  theme(text=element_text(family="arial", face="bold", size=12))+
  theme(axis.title.y = element_text(face="bold", family = "arial", vjust=1.5, colour="black", hjust = 0.5, size=rel(1.2)))+
  theme(axis.title.x = element_text(face="bold", family = "arial", vjust=0.5, colour="black", size=rel(1.2)))+
  theme(axis.text.x = element_text(family= "sans",face = "plain", colour="black", size=rel(1.1)))+
  theme(axis.text.y = element_text(family= "sans",face = "plain", colour="black", size=rel(1.1)))+
  theme(axis.line = element_line(size = 1, colour = "black"))+
  theme(legend.title = element_text(colour="black", size=12, face="bold", family = "arial"))+
  theme(legend.key = element_rect(fill = "white"))

# Simple and prefered solution: Facet by e.g. by year
w1 <- ggplot(data = mmp2) +
  geom_line(mapping = aes(x = Fecha, y = Tmin, colour="Min"), size=0.71) +
  geom_line(mapping = aes(x = Fecha, y = T, colour="P"), size=0.71) +
  geom_line(mapping = aes(x = Fecha, y = Tmax, colour="Max"), size=0.71) +
  scale_x_date(date_breaks = "1 day", date_labels = "%d-%m", expand = (c(0.001,0.008)))+
  scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(1,18), expand=c(0,0)) +
  scale_colour_manual(name="Leyenda",
                      values=c(Min="green", P="#56B4E9", Max="Red")) +
  ylab("Temperatura (C)")+
  xlab("Tiempo") +
  guides(colour=guide_legend(order = 2),
         shape=guide_legend(order = 2)) +
  facet_wrap(~year_fecha, scales = "free_x") +
  polish

w1  

# Hacky solutions with some manual labelling
labs <- select(mmp2, Fecha3, Fecha2) %>% 
  tibble::deframe()

date_lab <- function(x) {
  labs[as.character(x)]
}

# Draw the data as one continuous line
w2 <- ggplot(data = mmp2) +
  geom_line(mapping = aes(x = Fecha3, y = Tmin, colour="Min"), size=0.71) +
  geom_line(mapping = aes(x = Fecha3, y = T, colour="P"), size=0.71) +
  geom_line(mapping = aes(x = Fecha3, y = Tmax, colour="Max"), size=0.71) +
  scale_x_continuous(breaks = as.integer(names(labs)), labels = date_lab, expand = (c(0.001,0.008))) +
  scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(1,18), expand=c(0,0)) +
  scale_colour_manual(name="Leyenda",
                      values=c(Min="green", P="#56B4E9", Max="Red")) +
  ylab("Temperatura (C)")+
  xlab("Tiempo") +
  guides(colour=guide_legend(order = 2),
         shape=guide_legend(order = 2)) +
  polish
w2

# Separate lines for years by using different linetypes 
w3 <- ggplot(data = mmp2) +
  geom_line(mapping = aes(x = Fecha3, y = Tmin, colour="Min", linetype = year_fecha), size=0.71) +
  geom_line(mapping = aes(x = Fecha3, y = T, colour="P", linetype = year_fecha), size=0.71) +
  geom_line(mapping = aes(x = Fecha3, y = Tmax, colour="Max", linetype = year_fecha), size=0.71) +
  scale_x_continuous(breaks = as.integer(names(labs)), labels = date_lab, expand = (c(0.001,0.008))) +
  scale_y_continuous(breaks=seq(-4, 28, 2), limits = c(1,18), expand=c(0,0)) +
  scale_colour_manual(name="Leyenda",
                      values=c(Min="green", P="#56B4E9", Max="Red")) +
  ylab("Temperatura (C)")+
  xlab("Tiempo") +
  guides(colour=guide_legend(order = 2),
         shape=guide_legend(order = 2)) +
  polish
w3

reprex package (v0.3.0) 于 2020 年 3 月 28 日创建

【讨论】:

  • 你可能知道,但你可以通过只调用一次主题并使用长数据和只调用一次 geom_line 并传递线型美学来大幅改进你的绘图代码
  • 是的,我知道。但在我看来,完全修改其他用户的代码并不一定是他们学习和提高 R 技能的最佳方式。所以我尽量贴近原始代码,专注于解决主要问题。 (;
  • 我就是这么想的。我将 OP 指向我的评论,因为它主要是为他们准备的……我猜一次只有一件小事……
猜你喜欢
  • 2017-03-04
  • 1970-01-01
  • 2018-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 2021-03-17
  • 2020-04-30
相关资源
最近更新 更多