使用 POSIXct 和夏令时绘制条形图
Posted
技术标签:
【中文标题】使用 POSIXct 和夏令时绘制条形图【英文标题】:Plotly barcharts with POSIXct and daylight-savings-time 【发布时间】:2021-02-24 07:12:37 【问题描述】:我想在 x 轴上绘制带有时间戳的条形图时间序列。我的问题是 10 月的夏令时,因为 02:00 有 2 个时间戳,一个带有 CEST 时区,一个带有 CET。
plotly-barchart 叠加了这些值,当您将鼠标悬停在 barchart 上时,很难发现并且看起来像错误,因为您会发现该值与 y 轴不对应。
如何在不将tickmode
更改为“数组”并定义tickvals/ticktext
的情况下并排显示这两个条形?
library(plotly)
df <- structure(list(value = round(runif(46, 20, 26), 3),
timestamp = structure(c(1603576800, 1603584000, 1603587600, 1603591200, 1603594800, 1603598400,
1603602000, 1603605600, 1603609200, 1603612800, 1603616400, 1603620000,
1603623600, 1603627200, 1603630800, 1603634400, 1603638000, 1603641600,
1603645200, 1603648800, 1603652400, 1603656000, 1603659600, 1603576800,
1603584000, 1603587600, 1603591200, 1603594800, 1603598400, 1603602000,
1603605600, 1603609200, 1603612800, 1603616400, 1603620000, 1603623600,
1603627200, 1603630800, 1603634400, 1603638000, 1603641600, 1603645200,
1603648800, 1603652400, 1603656000, 1603659600),
class = c("POSIXct", "POSIXt"), tzone = "Europe/Berlin"),
col = c(rep("#FFBA00", 23), rep("#B9CC2E", 23)),
name = c(rep("Grp1", 23), rep("Grp2", 23))),
row.names = 1:46, class = "data.frame")
plot_ly(data = df, text = "text") %>%
add_trace(x = ~timestamp, y = ~value, type = "bar",
marker = list(color = ~col),
text = ~sprintf("Time: %s<br>Value: %s", timestamp, value),
hoverinfo = "text",
name = ~name) %>%
plotly::layout(xaxis = list(title = 'Time', type = "date"),
barmode = 'group')
【问题讨论】:
为什么排除tickvals/ticktext
的使用?我会使用 UTC tickvals
和 CET/CEST ticktext
。
因为我想保持 plotly 的动态刻度创建,因为地块也可能有 1000 个单独的条形图。
很遗憾,我认为您目前没有其他选择。 Here 是一个非常古老的 GitHub 问题 - 已关闭但似乎没有得到解决。如果您确实找到了其他东西,请告诉我。
相关声明:Changes our internal date linearization to use UTC rather than local milliseconds. Every day on a Plotly graph will now be 24 hours long, with no daylight shifts.
from here
【参考方案1】:
总结我的 cmets 为未来的读者提供答案:
plotly
目前不支持原生显示夏令时:
将我们的内部日期线性化更改为使用 UTC 而不是本地 毫秒。现在,Plotly 图表上的每一天都是 24 小时, 没有白昼变化。
来源:https://github.com/plotly/plotly.js/pull/1194#issue-95087563
因此,我知道解决此问题的唯一可能性是在 plotly 的 layout
函数中使用 tickvals
和 ticktext
参数(@SeGa 不需要,这是合理的,因为我们将有重复的刻度标签。不过,以下内容可能对其他人有帮助)。
library(plotly)
DF <- structure(list(value = round(runif(46, 20, 26), 3),
timestamp = structure(c(1603576800, 1603584000, 1603587600, 1603591200, 1603594800, 1603598400,
1603602000, 1603605600, 1603609200, 1603612800, 1603616400, 1603620000,
1603623600, 1603627200, 1603630800, 1603634400, 1603638000, 1603641600,
1603645200, 1603648800, 1603652400, 1603656000, 1603659600, 1603576800,
1603584000, 1603587600, 1603591200, 1603594800, 1603598400, 1603602000,
1603605600, 1603609200, 1603612800, 1603616400, 1603620000, 1603623600,
1603627200, 1603630800, 1603634400, 1603638000, 1603641600, 1603645200,
1603648800, 1603652400, 1603656000, 1603659600),
class = c("POSIXct", "POSIXt"), tzone = "Europe/Berlin"),
col = c(rep("#FFBA00", 23), rep("#B9CC2E", 23)),
name = c(rep("Grp1", 23), rep("Grp2", 23))),
row.names = 1:46, class = "data.frame")
# DF$timestamp_utc <- DF$timestamp
# attr(DF$timestamp_utc, "tzone") <- "UTC"
plot_ly(data = DF, text = "text") %>%
add_trace(x = ~as.numeric(timestamp), y = ~value, type = "bar",
marker = list(color = ~col),
text = ~sprintf("Time: %s<br>Value: %s", timestamp, value),
hoverinfo = "text",
name = ~name) %>%
plotly::layout(xaxis = list(title = 'Time',
ticktext = ~timestamp,
tickvals = ~as.numeric(timestamp),
tickmode = "array"),
barmode = 'group')
小修改:如果我们想不费吹灰之力地减少刻度标签的数量,我们可以在ticktext
和tickvals
中使用pretty
:
ticktext = ~pretty(timestamp),
tickvals = ~as.numeric(pretty(timestamp))
相关文档:Formatting Ticks in R
【讨论】:
以上是关于使用 POSIXct 和夏令时绘制条形图的主要内容,如果未能解决你的问题,请参考以下文章
Python使用matplotlib绘制柱状图(bar plot)实战:水平条形图垂直条形图分组条形图堆叠条形图