英文:
How to deal with time series data to create new x and y axis lines to ggplot graph?
问题
我尝试展示一个类似于基本R图形的ggplot图。我遇到的问题是处理时间序列数据(日期和时间),以正确绘制x轴和y轴。
我使用了Baptiste提供的相同方法来创建x轴和y轴函数: https://stackoverflow.com/questions/10808761/r-style-axes-with-ggplot
然而,它看起来不正确(见下面的图片)。我不确定如何修复y轴,我也不知道如何修复x轴,使得限制只在上午07:00:00和上午10:00:00之间。任何帮助将不胜感激!
#y轴
base_breaks_y <- function(x){
b <- pretty(x)
d <- data.frame(x=as.POSIXct(c("2019-01-30 07:00:00")), xend=as.POSIXct(c("2019-01-30 10:00:00")), y=min(b), yend=max(b))
list(geom_segment(data=d, aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE),
scale_y_continuous(breaks=b))
}
#x轴
base_breaks_x <- function(x){
b <- pretty(x)
d <- data.frame(y=-Inf, yend=-Inf, x=min(b), xend=max(b))
list(geom_segment(data=d, aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE),
scale_x_datetime(breaks=b, labels=date_format("%H:%M")))
}
#绘制
ggplot(data=df1, aes(x=date.time, y=value)) +
geom_line() +
#标签
ylab("Value") +
xlab("Time Series") +
#美观设定
theme_bw() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size=11)) +
#调整日期时间范围
base_breaks_x(df1$date.time) +
base_breaks_y(df1$value)
示例数据:
dput(df1)
structure(list(date.time = structure(c(1548833480, 1548833555,
1548833630, 1548833705, 1548833781, 1548833856, 1548833931, 1548834006,
1548834083, 1548834158, 1548834233, 1548834308, 1548834384, 1548834459,
1548834534, 1548834609, 1548834685, 1548834760, 1548834835,
1548834910, 1548834987, 1548835062, 1548835137, 1548835212, 1548835288,
1548835363, 1548835438, 1548835513, 1548835590, 1548835665, 1548835740,
1548835815, 1548835891, 1548835966, 1548836041, 1548836116, 1548836192,
1548836267, 1548836342, 1548836417, 1548836494, 1548836569, 1548836644,
1548836719, 1548836795, 1548836870, 1548836945, 1548837020, 1548837096,
1548837171, 1548837246, 1548837321, 1548837398, 1548837473, 1548837548,
1548837623, 1548837699, 1548837774, 1548837849, 1548837924, 1548838000,
1548838075, 1548838150, 1548838225, 1548838302, 1548838377, 1548838452,
1548838527, 1548838603, 1548838678, 1548838753, 1548838828, 1548838905,
1548838980, 1548839055, 1548839130, 1548839206, 1548839281, 1548839356,
1548839431, 1548839507, 1548839582, 1548839657, 1548839732, 1548839809,
1548839884, 1548839959, 1548840034, 1548840110, 1548840185, 1548840260,
1548840335, 1548840411, 1548840486, 1548840561, 1548840636, 1548840713,
1548840788, 1548840863, 1548840938), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
value = c(3139, 2261, 2147, 2184, 2469, 2356, 2231, 1894,
1679, 1710, 1634, 1642, 1611, 1484, 1415, 1404, 1367, 1343,
1261, 1252, 1190, 1135, 1072, 1014, 979, 943, 935, 947, 952,
943, 937, 938, 920, 887, 867, 910, 954, 1036, 1106, 1160,
1216, 1226, 1288, 1368, 1348, 1363, 1474, 1420, 1276, 1310,
1357, 1207, 1051, 951, 923, 963, 1002, 1044, 1118, 1178,
1217, 1246, 1201, 1305, 1352, 1367, 1379, 1375, 1433, 1537,
1625, 1663, 1756, 1831, 1802, 1858, 2003, 1915, 1874, 1847,
1850, 2028, 2220, 2396, 2689, 2063, 2857, 2021, 2140, 2282,
2397, 2613, 2590, 2662, 2615, 2693, 2802, 2805, 2945, 3151
)), row.names = c(NA
英文:
I'm trying to present a ggplot graph similar to Base R graphs. The issue I have is dealing with time series data (date and time) to draw the x and y axis properly.
I used the same approach provided by Baptiste to create an x and y axis function: <https://stackoverflow.com/questions/10808761/r-style-axes-with-ggplot>
However, it doesn't look right (see image below). I am not sure how to fix the y-axis and I also don't know how to fix the x-axis so that the limits are only between 07:00:00AM and 10:00:00AM. Any help would be appreciated!
#y-axis
base_breaks_y <- function(x){
b <- pretty(x)
d <- data.frame(x=as.POSIXct(c("2019-01-30 07:00:00")), xend=as.POSIXct(c("2019-01-30 10:00:00")), y=min(b), yend=max(b))
list(geom_segment(data=d, aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE),
scale_y_continuous(breaks=b))
}
#x-axis
base_breaks_x <- function(x){
b <- pretty(x)
d <- data.frame(y=-Inf, yend=-Inf, x=min(b), xend=max(b))
list(geom_segment(data=d, aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE),
scale_x_datetime(breaks=b, labels=date_format("%H:%M")))
}
#plot
ggplot(data=df1, aes(x=date.time, y=value)) +
geom_line() +
#labels
ylab("Value") +
xlab("Time Series") +
#aesthetics
theme_bw() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size=11)) +
#scale date time range
base_breaks_x(df1$date.time) +
base_breaks_y(df1$value)
Example data:
> dput(df1)
structure(list(date.time = structure(c(1548833480, 1548833555,
1548833630, 1548833705, 1548833781, 1548833856, 1548833931, 1548834006,
1548834083, 1548834158, 1548834233, 1548834308, 1548834384, 1548834459,
1548834534, 1548834609, 1548834685, 1548834760, 1548834835, 1548834910,
1548834987, 1548835062, 1548835137, 1548835212, 1548835288, 1548835363,
1548835438, 1548835513, 1548835590, 1548835665, 1548835740, 1548835815,
1548835891, 1548835966, 1548836041, 1548836116, 1548836192, 1548836267,
1548836342, 1548836417, 1548836494, 1548836569, 1548836644, 1548836719,
1548836795, 1548836870, 1548836945, 1548837020, 1548837096, 1548837171,
1548837246, 1548837321, 1548837398, 1548837473, 1548837548, 1548837623,
1548837699, 1548837774, 1548837849, 1548837924, 1548838000, 1548838075,
1548838150, 1548838225, 1548838302, 1548838377, 1548838452, 1548838527,
1548838603, 1548838678, 1548838753, 1548838828, 1548838905, 1548838980,
1548839055, 1548839130, 1548839206, 1548839281, 1548839356, 1548839431,
1548839507, 1548839582, 1548839657, 1548839732, 1548839809, 1548839884,
1548839959, 1548840034, 1548840110, 1548840185, 1548840260, 1548840335,
1548840411, 1548840486, 1548840561, 1548840636, 1548840713, 1548840788,
1548840863, 1548840938), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
value = c(3139, 2261, 2147, 2184, 2469, 2356, 2231, 1894,
1679, 1710, 1634, 1642, 1611, 1484, 1415, 1404, 1367, 1343,
1261, 1252, 1190, 1135, 1072, 1014, 979, 943, 935, 947, 952,
943, 937, 938, 920, 887, 867, 910, 954, 1036, 1106, 1160,
1216, 1226, 1288, 1368, 1348, 1363, 1474, 1420, 1276, 1310,
1357, 1207, 1051, 951, 923, 963, 1002, 1044, 1118, 1178,
1217, 1246, 1201, 1305, 1352, 1367, 1379, 1375, 1433, 1537,
1625, 1663, 1756, 1831, 1802, 1858, 2003, 1915, 1874, 1847,
1850, 2028, 2220, 2396, 2689, 2063, 2857, 2021, 2140, 2282,
2397, 2613, 2590, 2662, 2615, 2693, 2802, 2805, 2945, 3151
)), row.names = c(NA, 100L), class = "data.frame")
答案1
得分: 2
One option to fix your issue would be to use x = xend = -Inf
for the y axis as in the original post but instead of setting it via the aesthetics, which will result in an error
> Error: Invalid input: time_trans works with objects of class POSIXct only
set them as arguments:
library(ggplot2)
library(scales)
base_breaks_y <- function(x) {
b <- pretty(x)
d <- data.frame(y = min(b), yend = max(b))
list(
geom_segment(
data = d, aes(y = y, yend = yend),
x = -Inf, xend = -Inf, inherit.aes = FALSE
),
scale_y_continuous(breaks = b)
)
}
ggplot(data = df1, aes(x = date.time, y = value)) +
geom_line() +
labs(y = "Value", x = "Time Series") +
theme_bw() +
theme(
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size = 11)
) +
base_breaks_x(df1$date.time) +
base_breaks_y(df1$value)
EDIT Getting the limits for the x axis right requires slightly more work. First we have to set the limits. Second, we have to take account of the limits when computing the breaks and the range for the geom_segment
:
base_breaks_x <- function(x, limits = NULL) {
x <- c(x, limits)
b <- pretty(x)
d <- data.frame(y = -Inf, yend = -Inf, x = min(b), xend = max(b))
list(
geom_segment(data = d, aes(x = x, y = y, xend = xend, yend = yend), inherit.aes = FALSE),
scale_x_datetime(
breaks = b, labels = date_format("%H:%M"),
limits = limits
)
)
}
ggplot(data = df1, aes(x = date.time, y = value)) +
geom_line() +
labs(y = "Value", x = "Time Series") +
theme_bw() +
theme(
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size = 11)
) +
base_breaks_x(
df1$date.time,
limits = as.POSIXct(c("2019-01-30 07:00:00", "2019-01-30 10:00:00"), tz = "GMT")
) +
base_breaks_y(df1$value)
英文:
One option to fix your issue would be to use x = xend = -Inf
for the y axis as in the original post but instead of setting it via the aesthetics, which will result in an error
> Error: Invalid input: time_trans works with objects of class POSIXct only
set them as arguments:
library(ggplot2)
library(scales)
base_breaks_y <- function(x) {
b <- pretty(x)
d <- data.frame(y = min(b), yend = max(b))
list(
geom_segment(
data = d, aes(y = y, yend = yend),
x = -Inf, xend = -Inf, inherit.aes = FALSE
),
scale_y_continuous(breaks = b)
)
}
ggplot(data = df1, aes(x = date.time, y = value)) +
geom_line() +
labs(y = "Value", x = "Time Series") +
theme_bw() +
theme(
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size = 11)
) +
base_breaks_x(df1$date.time) +
base_breaks_y(df1$value)
EDIT Getting the limits for the x axis right requires slightly more work. First we have to set the limits. Second, we have to take account of the limits when computing the breaks and the range for the geom_segment
:
base_breaks_x <- function(x, limits = NULL) {
x <- c(x, limits)
b <- pretty(x)
d <- data.frame(y = -Inf, yend = -Inf, x = min(b), xend = max(b))
list(
geom_segment(data = d, aes(x = x, y = y, xend = xend, yend = yend), inherit.aes = FALSE),
scale_x_datetime(
breaks = b, labels = date_format("%H:%M"),
limits = limits
)
)
}
ggplot(data = df1, aes(x = date.time, y = value)) +
geom_line() +
labs(y = "Value", x = "Time Series") +
theme_bw() +
theme(
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size = 11)
) +
base_breaks_x(
df1$date.time,
limits = as.POSIXct(c("2019-01-30 07:00:00", "2019-01-30 10:00:00"), tz = "GMT")
) +
base_breaks_y(df1$value)
答案2
得分: 1
以下是您要翻译的内容:
"It is a little bit confusing to me why you need to have custom functions. See the solution below for a straightforward way of using scale_...
to get your desired output."
"但如果有其他原因需要使用自定义函数,那么我们需要更改一些内容:"
"You need to set the timezones for your y
segment (a.k.a y-axis) to be the same as your input data. Moreover, x
and xend
both should be set to your date.time
minimum time."
"您需要将y
段(即y轴)的时区设置为与输入数据相同。此外,x
和xend
都应设置为您的date.time
的最小时间。"
"You need to put your x
segment (a.k.a x-axis) at minimum of Value
, not -Inf
. Hence, I added a second argument to take Value
and pass that to geom_segment
."
"您需要将x
段(即x轴)放置在Value
的最小值上,而不是-Inf
。因此,我添加了第二个参数来接受Value
并将其传递给geom_segment
。"
"I have also used expand(c(0,0))
in both scale_...
functions to remove the space between the tickmarks and the segments which are replacing the axes."
"我还在scale_...
函数中都使用了expand(c(0,0))
,以去除刻度标记和替代坐标轴的线段之间的空间。"
英文:
It is a little bit confusing to me why you need to have custom functions. See the solution below for a straightforward way of using scale_...
to get your desired output.
library(ggplot2)
library(scales)
ggplot(data=df1, aes(x=date.time, y=value)) +
geom_line() +
ylab("Value") +
xlab("Time Series") +
theme_bw() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"),
text = element_text(size=11)) +
scale_x_datetime(limits = range(pretty(df1$date.time)),
labels=date_format("%H:%M"),
expand = c(0,0)) +
scale_y_continuous(limits=range(pretty(df1$value)),
expand = c(0,0))
But if there are other reasons to use custom functions, then we need to change couple of things:
-
You need to set the timezones for your
y
segment (a.k.a y-axis) to be the same as your input data. Moreover,x
andxend
both should be set to yourdate.time
minimum time. -
You need to put your
x
segment (a.k.a x-axis) at minimum ofValue
, not-Inf
. Hence, I added a second argument to takeValue
and pass that togeom_segment
. -
I have also used
expand(c(0,0))
in bothscale_...
functions to remove the space between the tickmarks and the segments which are replacing the axes.
#y-axis
base_breaks_y <- function(y){
b <- pretty(y)
d <- data.frame(x=as.POSIXct(c("2019-01-30 07:30:00"), tz= "UTC"),
xend=as.POSIXct(c("2019-01-30 7:30:00"), tz= "UTC"),
y=min(b), yend=max(b))
list(geom_segment(data=d, aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE),
scale_y_continuous(breaks=b, expand = c(0,0)))
}
#x-axis
base_breaks_x <- function(x,y){
b <- pretty(x)
c <- pretty(y)
d <- data.frame(y=min(c), yend=min(c), x=min(b), xend=max(b))
list(geom_segment(data=d, aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE),
scale_x_datetime(breaks=b, labels=date_format("%H:%M"), expand = c(0,0)))
}
#plot
ggplot(data=df1, aes(x=date.time, y=value)) +
geom_line() +
#labels
ylab("Value") +
xlab("Time Series") +
#aesthetics
theme_bw() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
text = element_text(size=11)) +
#scale date time range
base_breaks_x(df1$date.time, df1$value) +
base_breaks_y(df1$value)
<sup>Created on 2023-05-22 with reprex v2.0.2</sup>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论