代码之家  ›  专栏  ›  技术社区  ›  bill999

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

  •  0
  • bill999  · 技术社区  · 6 年前

    我可以做一个 ggplot2 用相同的X轴(例如,年),但不同的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(天=8),或~。-8*60*60。非线性转换将返回错误。为了在这一上下文中生成事件次要轴的时间,用户可以考虑调整二次轴标签。

    0 回复  |  直到 6 年前
        1
  •  1
  •   Jon Spring    6 年前

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

    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