条形宽度可变的条形图
Bar Chart with variable width of bars
我正在尝试创建某种类型的 barchart/histogram,其中栏的宽度取决于两列。 s1 = 开始时间 s2 = 停止时间。我的 x 轴是从午夜到午夜的 24 小时。因此,如果一行为 s1 = 12:00 AM s2 = 1:45 AM 那么柱将从 12:00 am 到 1:45 AM,如果下一行是 s1 = 2:00 AM s2 = 2:30 AM 柱状图会比第一个更窄,因为与第一个柱状图的 1.75 小时相比,它只持续 30 分钟。然后高度取决于第三列值,它也是连续数据。如果有另一种可视化,我也愿意接受。时间之间不应该有重叠,但是如果有条 transparent/a 模式来显示有一些重叠会有所帮助。
下面是和我用的类似的少量数据
s1 | s2 | Value
1/1/2018 12:00 AM | 1/1/2018 1:45 AM | 10.2
1/1/2018 2:00 AM | 1/1/20182:30 AM | 3.1
应该这样做:
dat <- data.frame(start = c("1/1/2018 12:00 AM", "1/1/2018 2:00 AM"),
stop = c("1/1/2018 1:45 AM", "1/1/2018 2:30 AM"),
value = c(10.2, 3.1))
dat$start <- strptime(dat$start, "%d/%m/%Y %I:%M %p")
dat$stop <- strptime(dat$stop, "%d/%m/%Y %I:%M %p")
lower <- as.POSIXct(strftime(min(dat$start),"%Y-%m-%d"))
upper <- as.POSIXct(strftime(as.Date(max(dat$start))+1,"%Y-%m-%d"))-1
limits = c(lower,upper)
ggplot(dat) +
geom_rect(aes(xmin = dat$start, xmax = dat$stop,
ymin = 0, ymax = dat$value), alpha = 0.8, color = "black") +
scale_x_datetime(
date_breaks = "2 hour",
date_minor_breaks = "1 hour",
labels = date_format("%H:%M", tz = "CET"),
limits = limits)
如果您没有重叠 and/or y 描述类别,您可以考虑 ggalt
包中的 geom_dumbbell
。对于大量数据,您还可以考虑geom_horizon
(相同的包)
我认为这应该可行!方法是重塑数据,使每次只有一个值,包括在两次之间添加零值。然后你可以只使用 geom_step
来绘制。这本身并不是真正的 "barplot",因为它们应该用于分类数据。您的数据看起来更像是一个连续的时间序列,在特定位置没有值,因此我们只需为该序列构建正确的数据。
我认为添加权限行的步骤感觉比它们应该的更复杂 - 如果有人有任何改进建议,请随意!
library(tidyverse)
tbl <- tribble(
~s1, ~s2, ~value,
"1/1/2018 12:00 AM", "1/1/2018 1:45 AM", 10.2,
"1/1/2018 2:00 AM", "1/1/2018 2:30 AM", 3.1
) %>%
mutate_at(vars(s1, s2), lubridate::dmy_hm) %>%
gather("s", "datetime", s1, s2) %>%
arrange(datetime)
tbl_1 <- tbl %>% bind_cols(id = group_indices(tbl, value))
tbl_2 <- tbl_1 %>%
group_by(id) %>%
summarise(datetime = last(datetime)) %>%
mutate(s = "s4", value = 0) %>%
bind_rows(tbl_1, .)
full_tbl <- tbl_2 %>%
group_by(id) %>%
summarise(datetime = first(datetime)) %>%
mutate(s = "s0", value = 0) %>%
bind_rows(., tbl_2) %>%
arrange(datetime, s)
print(full_tbl)
#> # A tibble: 8 x 4
#> id datetime s value
#> <int> <dttm> <chr> <dbl>
#> 1 2 2018-01-01 00:00:00 s0 0
#> 2 2 2018-01-01 00:00:00 s1 10.2
#> 3 2 2018-01-01 01:45:00 s2 10.2
#> 4 2 2018-01-01 01:45:00 s4 0
#> 5 1 2018-01-01 02:00:00 s0 0
#> 6 1 2018-01-01 02:00:00 s1 3.10
#> 7 1 2018-01-01 02:30:00 s2 3.10
#> 8 1 2018-01-01 02:30:00 s4 0
ggplot(data = full_tbl) + geom_step(aes(x = datetime, y = value))
我正在尝试创建某种类型的 barchart/histogram,其中栏的宽度取决于两列。 s1 = 开始时间 s2 = 停止时间。我的 x 轴是从午夜到午夜的 24 小时。因此,如果一行为 s1 = 12:00 AM s2 = 1:45 AM 那么柱将从 12:00 am 到 1:45 AM,如果下一行是 s1 = 2:00 AM s2 = 2:30 AM 柱状图会比第一个更窄,因为与第一个柱状图的 1.75 小时相比,它只持续 30 分钟。然后高度取决于第三列值,它也是连续数据。如果有另一种可视化,我也愿意接受。时间之间不应该有重叠,但是如果有条 transparent/a 模式来显示有一些重叠会有所帮助。
下面是和我用的类似的少量数据
s1 | s2 | Value
1/1/2018 12:00 AM | 1/1/2018 1:45 AM | 10.2
1/1/2018 2:00 AM | 1/1/20182:30 AM | 3.1
应该这样做:
dat <- data.frame(start = c("1/1/2018 12:00 AM", "1/1/2018 2:00 AM"),
stop = c("1/1/2018 1:45 AM", "1/1/2018 2:30 AM"),
value = c(10.2, 3.1))
dat$start <- strptime(dat$start, "%d/%m/%Y %I:%M %p")
dat$stop <- strptime(dat$stop, "%d/%m/%Y %I:%M %p")
lower <- as.POSIXct(strftime(min(dat$start),"%Y-%m-%d"))
upper <- as.POSIXct(strftime(as.Date(max(dat$start))+1,"%Y-%m-%d"))-1
limits = c(lower,upper)
ggplot(dat) +
geom_rect(aes(xmin = dat$start, xmax = dat$stop,
ymin = 0, ymax = dat$value), alpha = 0.8, color = "black") +
scale_x_datetime(
date_breaks = "2 hour",
date_minor_breaks = "1 hour",
labels = date_format("%H:%M", tz = "CET"),
limits = limits)
如果您没有重叠 and/or y 描述类别,您可以考虑 ggalt
包中的 geom_dumbbell
。对于大量数据,您还可以考虑geom_horizon
(相同的包)
我认为这应该可行!方法是重塑数据,使每次只有一个值,包括在两次之间添加零值。然后你可以只使用 geom_step
来绘制。这本身并不是真正的 "barplot",因为它们应该用于分类数据。您的数据看起来更像是一个连续的时间序列,在特定位置没有值,因此我们只需为该序列构建正确的数据。
我认为添加权限行的步骤感觉比它们应该的更复杂 - 如果有人有任何改进建议,请随意!
library(tidyverse)
tbl <- tribble(
~s1, ~s2, ~value,
"1/1/2018 12:00 AM", "1/1/2018 1:45 AM", 10.2,
"1/1/2018 2:00 AM", "1/1/2018 2:30 AM", 3.1
) %>%
mutate_at(vars(s1, s2), lubridate::dmy_hm) %>%
gather("s", "datetime", s1, s2) %>%
arrange(datetime)
tbl_1 <- tbl %>% bind_cols(id = group_indices(tbl, value))
tbl_2 <- tbl_1 %>%
group_by(id) %>%
summarise(datetime = last(datetime)) %>%
mutate(s = "s4", value = 0) %>%
bind_rows(tbl_1, .)
full_tbl <- tbl_2 %>%
group_by(id) %>%
summarise(datetime = first(datetime)) %>%
mutate(s = "s0", value = 0) %>%
bind_rows(., tbl_2) %>%
arrange(datetime, s)
print(full_tbl)
#> # A tibble: 8 x 4
#> id datetime s value
#> <int> <dttm> <chr> <dbl>
#> 1 2 2018-01-01 00:00:00 s0 0
#> 2 2 2018-01-01 00:00:00 s1 10.2
#> 3 2 2018-01-01 01:45:00 s2 10.2
#> 4 2 2018-01-01 01:45:00 s4 0
#> 5 1 2018-01-01 02:00:00 s0 0
#> 6 1 2018-01-01 02:00:00 s1 3.10
#> 7 1 2018-01-01 02:30:00 s2 3.10
#> 8 1 2018-01-01 02:30:00 s4 0
ggplot(data = full_tbl) + geom_step(aes(x = datetime, y = value))