R-如何使用带有不同时间变量的两个y轴绘制带有y轴的ggplot2 *

时间:2019-10-12 22:15:51

标签: r ggplot2 scale gganimate

我可以使用相同的x轴(例如,年份)绘制一个ggplot2图,但是使用不同的y轴(比例非常不同。可以使用gganimate来为两条线设置动画) ,每个都对应于自己的y轴?我已经能够使用相同的y轴创建两条线,但无法弄清楚如何使用两个轴。

我认为在我的特定情况下,该问题可能与我的y轴变量为POSIX格式有关。

假设我按如下方式创建a数据集:

library(ggplot2)
library(gganimate)
library(htmltab)
library(lubridate)

#marathon
data0 <- htmltab("https://en.wikipedia.org/wiki/Marathon_world_record_progression",1)
data <- data0[,c(1,4)]
#remove ones that are ARRS only
data <- data[-c(9,12,13,22,27,33,34,35,36,51),]
#data <- data %>% mutate(time = Time %>% hms())
data$time2 <- as.POSIXct(data$Time, format = "%H:%M:%S")
data$date <- mdy(data$Date)
data$race <- "Marathon"

#mile
mile0 <- htmltab("https://en.wikipedia.org/wiki/Mile_run_world_record_progression",4)
mile <- mile0[,c(1,4)]
#mile <- mile0 %>% mutate(time = Time %>% ms())
mile$time2 <-  as.POSIXct(mile$Time, format = "%M:%S")
mile$date <- dmy(mile$Date)
mile$race <- "Mile"

marathon <- data[,c(3,4)]
names(marathon)[1]<-"marathon"

mile2 <- mile[,c(3,4)]
names(mile2)[1]<-"mile"
a <- merge(marathon, mile2, by="date", all=TRUE)

然后我可以制作一个gganimate动画,如下所示:

ggplot(a) +
    geom_point(aes(x=date, y=marathon, group=date, color="blue")) +
    geom_point(aes(x=date, y=mile, group=date, color="red")) +
    scale_y_continuous(sec.axis = sec_axis(~./152, name = "CDF"), breaks=seq(0,150,25))
    transition_reveal(date)

问题在于两者的比例截然不同(一个约为2-3小时,而另一个约为2.5-3.5分钟)。如何获得相同规模的产品?如果它们使用的是正常格式,则我可以执行以下操作:

ggplot(a) +
    geom_point(aes(x=date, y=marathon, group=date, color="blue")) +
    geom_point(aes(x=date, y=mile*65, group=date, color="red")) +
    scale_y_continuous(sec.axis = sec_axis(~./65, name = "Mile"), breaks=seq(0,150,25)) +
    transition_reveal(date)

但是,由于y变量所处的POSIX格式,我得到了一个错误。我该怎么办? (理想情况下,我想按比例缩放它们,以便每个变量的垂直范围基本上能填充垂直距离。)

作为参考,这是我要修复的绘图结果:

enter image description here

我担心这不可能。参见https://ggplot2.tidyverse.org/reference/sec_axis.html

“从v3.1开始,日期和日期时间刻度具有有限的辅助轴功能。与其他连续刻度不同,日期和日期时间刻度的辅助轴转换必须遵循其主要POSIX数据结构。这意味着只能通过加法转换或减法,例如〜。+ hms :: hms(days = 8),或〜。-8 * 60 * 60。非线性变换将返回错误。在这种情况下,要生成时间自事件的辅助轴,用户可以考虑修改辅助轴标签。”

1 个答案:

答案 0 :(得分:1)

一种方法是将时间转换为十进制小时(或分钟等)并调整比例尺标签:

library(dplyr);  library(lubridate)
a %>%
  # tidyr::gather(type, time, -date) %>% 
  tidyr::pivot_longer(-date, "type", "time") %>%   # Preferred syntax since tidyr 1.0.0
  mutate(time_dec = hour(value) + minute(value)/60 + second(value)/3600,
         time_scaled = time_dec * if_else(type == "mile", 30, 1)) %>% 
  ggplot() +
  geom_point(aes(x=date, y=time_scaled, group=value, color = type)) +
  scale_y_continuous(breaks = 0:3, 
                     labels = c("0", "1:00", "2:00", "3:00"),
                     name = "Marathon",
                     sec.axis = sec_axis(~./30, 
                                         name = "Mile", 
                                         breaks = (1/60)*0:100,
                                         labels = 0:100)) +
  expand_limits(y = c(1.5,3)) +
  transition_reveal(date)

enter image description here