如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

huangapple go评论71阅读模式
英文:

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!

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

#y-axis
base_breaks_y &lt;- function(x){
  b &lt;- pretty(x)
  d &lt;- data.frame(x=as.POSIXct(c(&quot;2019-01-30 07:00:00&quot;)), xend=as.POSIXct(c(&quot;2019-01-30 10:00:00&quot;)), 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 &lt;- function(x){
  b &lt;- pretty(x)
  d &lt;- 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(&quot;%H:%M&quot;)))
}
#plot 
ggplot(data=df1, aes(x=date.time, y=value)) +
  geom_line() +
  #labels 
  ylab(&quot;Value&quot;) +
  xlab(&quot;Time Series&quot;) +
  #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:

 &gt; 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(&quot;POSIXct&quot;, &quot;POSIXt&quot;), tzone = &quot;UTC&quot;), 
    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 = &quot;data.frame&quot;)

答案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)

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

英文:

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 &lt;- function(x) {
  b &lt;- pretty(x)
  d &lt;- 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 = &quot;Value&quot;, x = &quot;Time Series&quot;) +
  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)

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

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 &lt;- function(x, limits = NULL) {
  x &lt;- c(x, limits)
  b &lt;- pretty(x)
  
  d &lt;- 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(&quot;%H:%M&quot;),
      limits = limits
    )
  )
}

ggplot(data = df1, aes(x = date.time, y = value)) +
  geom_line() +
  labs(y = &quot;Value&quot;, x = &quot;Time Series&quot;) +
  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(&quot;2019-01-30 07:00:00&quot;, &quot;2019-01-30 10:00:00&quot;), tz = &quot;GMT&quot;)
  ) +
  base_breaks_y(df1$value)

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

答案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轴)的时区设置为与输入数据相同。此外,xxend都应设置为您的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(&quot;Value&quot;) +
  xlab(&quot;Time Series&quot;) +
  theme_bw() +
  theme(panel.border = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.line = element_line(colour = &quot;black&quot;),
        text = element_text(size=11)) +
  scale_x_datetime(limits = range(pretty(df1$date.time)), 
                   labels=date_format(&quot;%H:%M&quot;), 
                   expand = c(0,0)) +
  scale_y_continuous(limits=range(pretty(df1$value)), 
                     expand = c(0,0))

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?



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 and xend both should be set to your date.time minimum 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.

  • 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.

#y-axis
base_breaks_y &lt;- function(y){
  b &lt;- pretty(y)
  d &lt;- data.frame(x=as.POSIXct(c(&quot;2019-01-30 07:30:00&quot;), tz= &quot;UTC&quot;),
                  xend=as.POSIXct(c(&quot;2019-01-30 7:30:00&quot;), tz= &quot;UTC&quot;), 
                  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 &lt;- function(x,y){
  b &lt;- pretty(x)
  c &lt;- pretty(y)
  d &lt;- 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(&quot;%H:%M&quot;), expand = c(0,0)))
}
#plot 
ggplot(data=df1, aes(x=date.time, y=value)) +
  geom_line() +
  #labels 
  ylab(&quot;Value&quot;) +
  xlab(&quot;Time Series&quot;) +
  #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)

如何处理时间序列数据以创建新的 x 和 y 轴线到 ggplot 图形?

<sup>Created on 2023-05-22 with reprex v2.0.2</sup>

huangapple
  • 本文由 发表于 2023年5月22日 13:29:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76303256.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定