【问题标题】:Flow duration curve using facet_wrap of ggplot in R?在 R 中使用 ggplot 的 facet_wrap 的流持续时间曲线?
【发布时间】:2020-05-11 20:42:45
【问题描述】:

我正在使用fdc 中的hydroTSM package。我有三个data.frame,我想使用ggplotfacet_wrap 功能构建data.frame 的流动持续时间曲线(FDC),以便在three rowsone column 中拥有plots。以下将为DF1 生成FDC curves

library(tidyverse)
library(hydroTSM)
library(gridExtra)

DF1 = data.frame(Ob = runif(1000,0,500), A = runif(1000,0,700), B = runif(1000,2,800))
DF2 = data.frame(Ob = runif(1000,0,500), A = runif(1000,0,700), B = runif(1000,2,800))
DF3 = data.frame(Ob = runif(1000,0,500), A = runif(1000,0,700), B = runif(1000,2,800))

fdc(DF1, plot = TRUE)

我尝试使用gridExtra packagegrid.arrange 将三个图强制在一个数字上。我不仅没有做到这一点,而且它不是首选方法。我想使用ggplotfacet_wrap 选项。实际上,使用DF1 数据错误地绘制了该图。我正在寻找类似下面的东西:

更新:这是基于@Jon Spring 的建议。

graphics.off()
rm(list = ls())

library(tidyverse)
library(hydroTSM)
library(gridExtra)

DF1 = data.frame(Ob = runif(800,0,500), M1= runif(800,0,700), M2 = runif(800,2,800), df = rep("Upstream", 800))
DF2 = data.frame(Ob = runif(1000,0,500), M1 = runif(1000,0,700), M2 = runif(1000,2,800), df = rep("Midstream", 1000))
DF3 = data.frame(Ob = runif(1000,0,500), M1 = runif(1000,0,700), M2 = runif(1000,2,800), df = rep("Downstream", 1000))

# combine data into one table with id column for the source
 bind_rows(DF1, DF2, DF3) %>% 
   # reshape into longer format
  pivot_longer(-df, names_to = "src", values_to = "flow") %>%
  arrange(-flow) %>%
  group_by(df, src) %>%
  mutate(flow_pct = 1 - percent_rank(flow)) %>%
  ungroup() %>%

  ggplot(aes(flow_pct, flow, color = src)) +
  geom_line() +
  theme_light() +
  facet_wrap(~df, ncol = 1) +
  labs(x = "% Time flow equalled or exceeded",
       y = "Q, [m3/s]") +
  theme(strip.text = element_text(hjust = 0, color = "black"),
        strip.background = element_blank())

【问题讨论】:

  • 为了使用 faceting,ggplot 需要一个列来解释哪一行属于哪个 facet。你知道吗?
  • @Hydro:您可以添加scale_y_log10(labels = scales::comma) + annotation_logticks(sides = 'l') + 以使绘图看起来类似于hydroTSM::fdc() 函数的输出。

标签: r ggplot2 probability facet-wrap hydrotsm


【解决方案1】:

你可以在 ggplot 中用 facets 做这样的事情:

library(tidyverse)
# combine data into one table with id column for the source
bind_rows(DF1, DF2, DF3, .id = "df") %>% 
  mutate(df = LETTERS[as.numeric(df)]) %>%
  # reshape into longer format
  pivot_longer(-df, names_to = "src", values_to = "flow") %>%
  arrange(-flow) %>%
  group_by(df, src) %>%
  mutate(flow_pct = 1 - percent_rank(flow)) %>%
  ungroup() %>%

  ggplot(aes(flow_pct, flow, color = src)) +
  geom_line() +
  theme_light() +
  facet_wrap(~df, ncol = 1) +
  labs(x = "% Time flow equalled or exceeded",
       y = "Q, [m3/s]") +
  theme(strip.text = element_text(hjust = 0, color = "black"),
        strip.background = element_blank())

如果您想将字母注释放在更左侧,您可以交替使用patchwork 包来堆叠和标记图:

library(tidyverse)
library(patchwork)

flow_plot <- function(df) {
  df %>% 
  pivot_longer(everything(), names_to = "src", values_to = "flow") %>%
  arrange(-flow) %>%
  group_by(src) %>%
  mutate(flow_pct = 1 - percent_rank(flow)) %>%
  ungroup() %>%

  ggplot(aes(flow_pct, flow, color = src)) +
  geom_line() +
  theme_light() +
  guides(color = guide_legend()) +
  labs(x = "% Time flow equalled or exceeded",
       y = "Q, [m3/s]") +
    theme(legend.position = c(0.85,0.6))
}


flow_plot(DF1) /
  flow_plot(DF2) /
  flow_plot(DF3) +
  plot_annotation(tag_levels = "A")

【讨论】:

  • 这太好了-谢谢。是否可以将列 df row names 更改为其他内容,例如好、坏和丑而不是 A、B、C。我尝试了 mutate(df = c(Good', 'Bad','ugly')[ as.numeric(df)])` 它不起作用。我也尝试用 'row.names' 更改它,但没有成功。
  • 感谢您提出的所有好建议。我从您的解决方案中学到了很多东西。我仍然需要更改绘图的顺序。上游应该是第一个,然后是中游,然后是下游。
【解决方案2】:

对于示例数据,我们将使用 HydroGOF 软件包中的 EgaEnEstellaQts 每日流量数据。这从 1961 年 1 月 1 日到 1970 年 12 月 31 日。创建三年的数据进行绘图

library(hydroGOF)
library(gridExtra)
library(tidyverse)

Q1 <- window(EgaEnEstellaQts, start=as.Date('1961-01-01'), end=as.Date('1961-12-31'))
Q2 <- window(EgaEnEstellaQts, start=as.Date('1963-01-01'), end=as.Date('1963-12-31'))
Q3 <- window(EgaEnEstellaQts, start=as.Date('1965-01-01'),  end=as.Date('1965-12-31'))


# Because these objects are all the same length, we can put them in one data frame

flow_df <- tibble(Q1 = coredata(Q1), Q2 = coredata(Q2), Q3 = coredata(Q3))

# Add percent ranks which we'll use to plot the fdc

p1 <- flow_df %>% 
  gather(key = period, value = flow)  %>% 
  group_by(period) %>% 
  mutate(rank = 1 - percent_rank(flow)) %>% 
  ggplot(aes(x = rank, y = flow, colour = period)) +
  geom_line() +
  scale_y_continuous(name = 'Discharge', trans = 'log10') +
  scale_x_continuous(name = 'Percentage of time flow is exceeded', breaks = seq(0,1,0.25), labels = c('0', '25%', '50%', '75%', '100%')) +
  labs(subtitle = 'A')


#Make the other graphs as required (just place holders here)    

p2 <- p1 + labs(subtitle = 'B')
p3 <- p1 + labs(subtitle = 'C')

# Arrange with grid arrange      
grid.arrange(p1, p2, p3)

【讨论】:

  • 感谢托尼的替代方案。然而,我有多个data.frames。一个用于upstream stations,一个用于midstream,一个用于downstream。每个位置data.frame 有多个列;一个用于observation data,另一个用于different modeling simulation。我想在这些位置比较FDCobservationmodel simulations
  • 谢谢@Hydro。如果您有兴趣,请在此处查看有趣的 FDC 图 tonyladson.wordpress.com/2018/12/04/flow-duration-curves
  • 托尼!网站上的所有优秀信息-感谢分享。我会怀着极大的兴趣浏览它们——与我的工作非常相关。我一直在寻找 API 来在萨斯喀彻温省的分水岭上对其进行测试——我一定会试一试,如果有什么不清楚的地方,我会继续询问。
猜你喜欢
  • 1970-01-01
  • 2018-08-24
  • 2020-11-05
  • 1970-01-01
  • 2015-12-15
  • 1970-01-01
  • 2021-01-16
  • 2016-03-12
  • 1970-01-01
相关资源
最近更新 更多