如何使用 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_tile
和 geom_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())
这是结果图:
我有几个数据集跨越一年的数据,收集了从 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_tile
和 geom_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())
这是结果图: