Giới thiệu

Những ai làm về thuỷ văn, chắc không còn lạ với cách biểu diễn đồ thị: phần trên là rainfall hyetograph, phần dưới là river flow, water discharge hoặc pollutograph. Cách đây mấy năm, một cái đồ thị coi như đơn giản vậy nhưng lúc đó hầu như không có ai chỉ cách vẽ dạng đồ thị này bằng R, hồi đó còn quá kém nên mình cũng phải tốn một khoảng thời gian nho nhỏ để vẽ được. Một cách tình cờ, hôm qua rblogger giới thiệu cách vẽ dạng đồ thị này bằng gói highcharter (https://www.r-bloggers.com/hyetographs-hydrographs-and-highcharter/)

Vì vậy hôm nay share cho các bạn luôn cách vẽ dạng đồ thị này bằng ggplot2 và so sánh với highcharter. Nhân tiện nói luôn nhân chủ để graph R base và ggplot2 đang hót, một trong những điểm yếu của ggplot2 đó là cách quản lí 2 hoặc nhiều trục x và y một lúc. Nếu bạn nào có cách làm được, mong chia sẻ.

Data

Mình có 2 serie dữ liệu: Rainfall(mm) và River flow (m3/s).

head(rainfall)
##                  Date Flow_simul
## 1 2012-08-01 00:00:00   6.288246
## 2 2012-08-01 00:09:00   6.288246
## 3 2012-08-01 00:10:00   0.130000
## 4 2012-08-01 00:20:00   6.288246
## 5 2012-08-01 00:29:00   6.288246
## 6 2012-08-01 00:30:00   0.130000
head(res17f)
##                  Date Rain
## 1 2012-08-01 00:00:00    0
## 2 2012-08-01 00:10:00    0
## 3 2012-08-01 00:20:00    0
## 4 2012-08-01 00:30:00    0
## 5 2012-08-01 00:40:00    0
## 6 2012-08-01 00:50:00    0

Vẽ bằng ggplot2

g.top <- ggplot(res17f, aes(x = Date, y = Rain, ymin=0, ymax=Rain)) +
  geom_linerange(colour = "blue") +
  scale_y_continuous(limits=c(22,0),expand=c(0,0), trans="reverse")+
  theme_classic() +
  theme(plot.margin = unit(c(5,5,-30,6),units="points"),
        axis.title.y = element_text(size =14))+
  labs(y = "Rain (mm)")

datebreaks <- seq(as.POSIXct(a2[1,1]), as.POSIXct(a2[nrow(a2),1]), by="1 month")

g.bottom <- ggplot(a2, aes(x = Date, y = Flow_simul)) +
  geom_line() +
  scale_shape_identity()+
  theme_classic() +
  theme(plot.margin = unit(c(0,5,1,1),units="points")) +
  labs(x = "Date", y = "River flow (m/s)")+
  scale_x_datetime(breaks = datebreaks, labels=date_format("%Y %b"))+
  theme(axis.text.x = element_text(angle=90, hjust=1))+
  theme(text = element_text(size = 13)) + theme(legend.position="bottom",legend.title=element_blank())
grid.arrange(g.top,g.bottom, heights = c(1/5, 3/5))
## Warning: Removed 1 rows containing missing values (geom_linerange).

Vẽ bằng highcharter

df <- merge(a2,res17f ,by = "Date",all = T)
df1 <- tidyr::gather(df,variable,value,-Date)

hc <- highchart() %>% 
  hc_yAxis_multiples(list(title = list(text = "rainfall(mm)"), reversed = TRUE,color = "blue"), 
                     list(title = list(text = "flow (m3/s)"), 
                          opposite = TRUE)) %>% 
  hc_add_series(data = filter(df1, variable == "Rain") %>% mutate(value = value) %>% .$value, type = "column") %>% 
  hc_add_series(data = filter(df1, variable == "Flow_simul") %>% .$value, type = "column", yAxis = 1) %>% 
  hc_xAxis(categories = df1$Date, title = list(text = "date"))
hc

Kết luận

  1. Giải pháp ggplot của bài viết trên r-blogger buộc phải dùng facet.
  2. Chỉ vài dòng trong highcharter là bạn giải quyết vấn đề ngon lành cành đào. Tuy nhiên cần phải tinh chỉnh lại một số những chi tiết mà điều này thì mình không biết là sẽ dễ hơn ở ggplot2 hay không.
  3. Nếu muốn thêm một đường kẻ ngang, cái điểm chú thích etc. vào hình trên thì mình nghĩ ggplot2 sẽ dễ làm hơn.

Chúc các bạn vui.