如何使用 ggplot2 在 R 中的极坐标中绘制一年的每小时(3 月 - 2 月)数据

How to graph a year's worth of hourly (March - Feb) data in polar coordinates in R with ggplot2

我有几个数据集跨越一年的数据,收集了从 2018 年 3 月到 2019 年 6 月的每小时读数。我希望能够仅隔离一年的数据(例如:2018 年 3 月 1 日 00:00:00 到 2019 年 2 月 28 日 23:00:00),并在极坐标中绘制。然而,我 运行 遇到的问题是,我希望极坐标图的顶部有 1 月(无关年份),而不是 2018 年 3 月。对此需要注意的是,我不想计算许多弧度我需要抵消图表的开始,因为我必须对几个不同的数据集执行此操作,这些数据集并非都从同一点开始(我已经搜索了数周以了解如何执行此操作)。如果这样做的唯一方法是用弧度抵消,那就这样吧,但也许有人有更好的主意。

这是我的数据集的示例:

library(lubridate)
NoOfHours <- as.numeric(ymd_hms("2019-6-1 17:00:00") - ymd_hms("2018-3-01 8:00:00"))*24 
data <- as.data.frame(ymd_hms("2018-3-01 8:00:00") + hours(0:NoOfHours))
colnames(data) <- 'date' 
set.seed(10)
data$level <- runif(nrow(data), min = 0, max = 150)

等级范围为0-150。其他一些数据集超过 200。

此外,我想应用渐变背景颜色,从 0 上升到 200 时从绿色变为红色。它将用于表示高值。这是我的意思的一个例子,虽然它不是极坐标图并且是有角度的(我找不到好的代表性图像):https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwi9oObnr9bkAhU5HTQIHdS6BdUQjRx6BAgBEAQ&url=https%3A%2F%2Fhelp.principaltoolbox.com%2FEN%2Fscatter_plot.html&psig=AOvVaw2E6Uanev3RNOW2rIbsTISa&ust=1568758598336572

最后,如果可能的话,我想在图的中心有一个洞,类似于圆环图,以便最低值在一年内更具可读性。目前我可以着手解决这个问题,但细节困扰着我。任何帮助,将不胜感激。

我可以分离出一年的数据并将其绘制在极坐标中。我正在使用此代码:

Hours <- format(as.POSIXct(strptime(data$date,"%Y-%m-%d %H:%M:%S",tz="")) ,format = "%H:%M:%S")
data$hours <- Hours

Date <- format(as.POSIXct(strptime(data$date,"%Y-%m-%d %H:%M:%S",tz="")) ,format = "%Y-%m-%d")
data$date_date <- Date #output

library(openair)
yeardata <- selectByDate(data, start = "2018-3-1", end = "2019-2-28", year = 2018:2019)

library(ggplot2)
plot <- ggplot(yeardata, aes(x=date, y=level)) +
    geom_line() +
    scale_colour_hue(l=50) + # Use a slightly darker palette than normal
    geom_smooth(method=lm,   # Add linear regression lines
                se=FALSE)  
plot
plot + coord_polar() + theme_minimal()

这最终产生了这张图: 一年剧情

虽然这接近我想要的,就像我上面提到的,但我需要它从一月开始(图表顶部),然后可能有一条线来表示年份分隔。

谢谢

这是一种通过将每个日期重新表示为 2019 日历年中的一天来规避 coord_polar 轮换问题的方法,这样数据将始终从 1 月 1 日开始,并且可以位于图表。 (否则您必须调整每组数据以表示第一个数据在一年中有多少天,然后将其乘以 2*pi/365 以设置您的起始角度。)

library(dplyr); library(lubridate)
data_1yr <- data %>%
  mutate(date19 = ymd(paste(2019, month(date), day(date)))) %>%
  mutate(day_num = 1 + (date - min(date))/ddays(1)) %>%
  filter(day_num <= 365)

如果要显示数千个单独的阴影区域,背景阴影绘制会很慢。要解决此问题,您可能需要取每日平均值并使用它来驱动阴影:

data_1yr_daily = data_1yr %>%
  group_by(date19) %>%
  summarize(level = mean(level))

然后我们可以绘制这两个,日均线驱动两个 geom_col,一个在正方向,一个在负方向。 (在这种情况下,我在使用 geom_tilegeom_rect 时遇到了一些麻烦,但这些可能更适合这个。)填充渐变如您所描述的那样,我起诉 ylim 指定一个范围比数据大,把馅饼做成甜甜圈。

ggplot(data = data_1yr, aes(x=date19, y=level)) +
  geom_col(data = data_1yr_daily, aes(fill = level, y = Inf), width = 1) +
  geom_col(data = data_1yr_daily, aes(fill = level, y = -50), width = 1) +
  geom_line() +
  scale_fill_gradient(low = "green", high = "red") +
  geom_smooth(method=lm,   # Add linear regression lines
              se=FALSE)  +
  coord_polar() +
  ylim(c(-150, 200)) +
  theme_minimal()

整合了 Jon Spring 的建议(再次感谢!)并进行了更多搜索,我几乎找到了我想要的东西。这是更新后的代码:

 library(ggplot2)

plot <- ggplot(yeardata, aes(x=date, y=level, color = level)) +
  geom_hline(yintercept = seq(0, 300, by = 50), colour = "black", size = 0.75, alpha = 0.3)+ #make my own gridlines so that when on a white background, the gridlines wont cross the text.
  scale_color_gradient(limits = c(0,200), low="green", high="red", oob = scales::squish)+ #need oob = scales::squish to get values over 200 to be red.
    geom_jitter(alpha = 0.2, size = 2) +# Use a slightly darker palette than normal
 theme(axis.title=element_text(size=16,face="bold"), axis.text.x = element_text(size = 16), axis.text.y = element_text(size = 12))+
   labs(x = NULL, y = bquote('Levels '~(m^2)), color = "Level")+ #bquote to allow superscripts
  scale_y_continuous(breaks = seq(0, 300, 50),
                     limits = c(-100,310))
plot
plot + coord_polar(start = ((2*60/365)*pi))+ #need to have the number of radians to get my start position. If march 1st is the start date, then 60 days have past since Jan 1.
  theme(legend.title = element_text(color = "black", size = 14, face = "bold"), panel.background = element_rect(fill = "white"), panel.grid  = element_blank())

这是结果图: