【问题标题】:hours scale in ggplot2ggplot2中的小时刻度
【发布时间】:2021-01-13 15:40:25
【问题描述】:

我正在处理就寝时间和起床时间,所以我想创建一个 24 小时 x 轴的图表,从第 1 天的下午 12 点开始,到第 2 天的下午 12 点结束。这意味着应该在晚上 11:59 之后开始又是 0。

同样的问题只有数字,我想创建一个从 10 到 20 的比例,20 之后再从 1 开始直到 10。

这是我现在拥有的代码:

ggplot(SLEEP2, aes(x=as.POSIXct(bedT, format="%H:%M"), y=Jour))+ 
geom_rect(aes(xmin=as.POSIXct(sleepT, format="%H:%M"), xmax=as.POSIXct(wakeT, 
format="%H:%M"),ymin=(Jour-0.4), ymax=(Jour+0.4)),fill="orange", 
color="black")+ scale_x_datetime()

我想用条形图表示他们的睡眠时间...

我该怎么做?我尝试了几个选项,但没有任何效果。 谢谢。

【问题讨论】:

  • 我想时间将是少数几个循环(“极地”)情节可能是可行选择的事情之一。例如,最近的一个帖子:stackoverflow.com/q/65589126/7941188
  • 感谢大家的回答,我仍在为我的数据和学习 R 苦苦挣扎,但我正在努力,多亏了你们的帮助,它才有所进展!一旦我可以走得更远,我会回到你身边! :)
  • 不客气。如果您对其中一个答案感到满意 - 请考虑以下事项:stackoverflow.com/help/someone-answers

标签: r ggplot2


【解决方案1】:

您可以使用scales_x_... 函数和自定义标签函数来实现您想要的。这是示例,由于您没有提供可重现的示例,因此我只是创建了自己的版本,可能并不完美,请随时检查和调整。

library(dplyr)
library(lubridate)
library(ggplot2)
df <- tibble(time = seq(from = as.POSIXct("2020-01-01 00:00:00"),
                        by = "1 hour", length.out = 48),
             number = seq(1, by = 1, length.out = 48),
             y_value = runif(48, min = 0, max = 60))

format_time_label <- function(x) {
  hour(x)
}

df[["hour"]] <- day(df[["time"]]) * hour(df[["time"]])
ggplot(data = df) +
  geom_bar(aes(x = time, y = y_value), stat = "identity") +
  scale_x_datetime(date_breaks = "1 hour", labels = format_time_label)

对于数字,我不确定你想要什么,所以我在每 20 次后重新启动回 1。

format_number_label <- function(x) {
  x[x %% 20 == 0] <- 20
  x[x > 20] <- x[x > 20] - (x[x > 20] %/% 20) * 20
  x
}

ggplot(data = df) +
  geom_bar(aes(x = number, y = y_value), stat = "identity") +
  scale_x_continuous(breaks = seq(1, by = 1, length.out = 48),
                     labels = format_number_label)

【讨论】:

    【解决方案2】:

    在底部编辑以包含给定的数据。

    如果有一种方法可以让图形的轴像我不知道的那样更直观。我想不通。

    正如其他人提到的,在您的代码中包含一些示例数据会很有帮助,这样解决方案就可以使用它,而不必猜测和/或自己编造。附上一张你拥有和/或想要的照片也很好。

    类似:

    R> head(SLEEP2)
    ...
    

    无论如何,这是一种方法。它一点也不优雅,但它确实有效。

    首先,制作一些在午夜达到峰值的“未转换”数据并绘制它。我猜这看起来就像你已经拥有的一样。

    library(tidyverse)
    library(lubridate)
    
    start <- ymd_hm("20210101-0000")
    # Make some pretend data. It's value is zero during the "day" and peaks around midnight.
    secsday <- 60*60*12
    df <- tibble(date_time = seq(start, start %m+% weeks(2), by=200)) %>%
        mutate(time = hms::as_hms(date_time),
               date = factor(date(date_time)),
               values = jitter(cos(day(date_time)/30+pi*as.numeric(time)/secsday), amount=1/40),
               values = ifelse(values>0, values, 0)
        )
    
    # Plot original data.
    ggplot(df, aes(time, values, colour=date)) +
        geom_line() +
        scale_x_time(breaks=hours(seq(0,24,6)), labels=c("midnight","6AM","noon","6pm","midnight")) +
        ggtitle('pre-transform')
    

    接下来,将 AM 翻译为 PM,将 PM 翻译为 AM。

    # Transform times so AM is PM and PM is AM (swap around noon).
    dt <- df %>% mutate(time=
                ifelse(time>hm("12:00"), hms::as_hms(time)-secsday, hms::as_hms(time)+secsday)
            )
    ggplot(dt, aes(time, values, colour=date)) +
        geom_line() +
        scale_x_time(breaks=hours(seq(0,24,6)), labels=c("noon", "6PM", "midnight", "6AM", "noon")) +
        ggtitle('post-transform')
    

    我想知道是否有办法通过只调整轴而不是数据来做到这一点。

    使用您提供的数据并使用条形:

    dat <- data.frame(Jour=1:5,
                      date=seq.Date(as.Date("2020-10-01"), as.Date("2020-10-05"), "day"),
                      sleeptime=c("22:30","21:10","23:00","23:00", "23:20"),
                      waketime= c("6:30", "7:00", "7:30", "6:25","7:10"))
    
    # make fake dates for sleep and wake
    dat <- dat %>% mutate(
                sleep = ymd_hm(paste(dat[1,]$date, sleeptime)),
                wake = ymd_hm(paste(dat[1,]$date, waketime)),
                wake = wake + ddays(ifelse(lubridate::hm(waketime)<lubridate::hm(sleeptime), 1, 0))
            )
    
    ggplot(dat, aes(xmin=sleep, xmax=wake)) +
        scale_x_datetime(breaks=ymd(dat[1,]$date) + hours(seq(12,36,length.out=5)),
                         labels=c("noon", "6PM", "midnight", "6AM", "noon"),
                         limits=ymd(dat[1,]$date) + hours(seq(12,36,length.out=2))
                         ) +
        geom_rect(ymin=0.25, ymax=0.75, fill='darkgreen') +
        ylim(0,1) +
        facet_grid(rows = vars(date)) +
        theme(axis.title = element_blank()) +
        theme(axis.text.y = element_blank(),
              axis.ticks = element_blank()
        )
    

    【讨论】:

    • 您可能需要考虑对“wake”和“sleep”使用“datetime”而不是“date”、“time”、“time”来消除歧义。
    • @tjebo - 你是对的。 “开始”时间在某个地方消失了。我将它和所需的库添加到第一个块中,所以现在它都是独立的。感谢您的提醒。
    【解决方案3】:

    将我的评论变成答案 - 我认为这是圆/极坐标系可能合适的少数时刻之一。

    我无耻地使用了来自user keithbjolley's answer 的数据和大量绘图代码 - 谢谢和+ 1。

    主要变化是对 coord_polar() 的调用。

    library(tidyverse)
    library(lubridate)
    
    start <- ymd_hm("20210101-0000")
    secsday <- 60 * 60 * 12
    df <- tibble(date_time = seq(start, start %m+% weeks(2), by = 200)) %>%
      mutate(
        time = hms::as_hms(date_time),
        date = factor(date(date_time)),
        values = jitter(cos(day(date_time) / 30 + pi * as.numeric(time) / secsday), amount = 1 / 40),
        values = ifelse(values > 0, values, 0)
      )
    
    reds <- grDevices::hcl.colors(length(unique(df$date)), "Reds")
    
    ggplot(df, aes(x = time, y = values, color = date)) +
      geom_line() +
      coord_polar(start = 0) +
      scale_color_manual(values = reds) +
      theme_minimal()
    

    reprex package (v0.3.0) 于 2021-01-19 创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多