r - x 轴上以可变条形宽度作为日期范围的条形图

标签 r ggplot2

我希望制作一个条形图,其中响应变量(体重变化)是在不同长度的时间段内测量的,由开始日期和结束日期定义。条形的宽度应与周期的长度相对应。我的数据的一个小例子:

wtchange.data <- structure(list(start.date = structure(1:3, .Label = c("2015-04-01", 
    "2015-04-15", "2015-04-30"), class = "factor"), end.date = structure(1:3, .Label = c("2015-04-15", 
    "2015-04-30", "2015-05-30"), class = "factor"), wtchange = c(5L, 
    10L, 15L), se = c(1.2, 2.5, 0.8)), .Names = c("start.date", "end.date", 
    "wtchange", "se"), class = "data.frame", row.names = c(NA, -3L
    ))

wtchange.data
#   start.date   end.date wtchange  se
# 1 2015-04-01 2015-04-15        5 1.2
# 2 2015-04-15 2015-04-30       10 2.5
# 3 2015-04-30 2015-05-30       15 0.8

wtchange.data$start.date <- as.Date(wtchange.data$start.date)
wtchange.data$end.date <- as.Date(wtchange.data$end.date)

尝试使用geom_bar :

library(ggplot2)
ggplot(wtchange.data, aes(x = start.date, y = wtchange)) +
  geom_bar(stat = "identity", color = "black") +
  geom_errorbar(aes(ymin = wtchange-se, ymax = wtchange+se), width = 1)

(不允许 >2 个信誉度 <10 的链接,因此遗憾的是无法显示第一个图)

主要问题是,当定义绘图区域的美观性 ( x = start.date, y = wtchange ) 时,我只能使用一个变量(本例中为 start.date)作为 x 轴,但是我确实需要以某种方式使用 start.dateend.date 来界定与每个周期相对应的条形宽度。该图应如下所示(用 Paint 绘制): enter image description here

第二个问题是条形图应该没有间隙地接触,但我不确定这是否可能,因为条形图必须具有不同的宽度,因此您不能为所有条形图设置一个条形图宽度。是否可以手动设置每个栏的宽度?


编辑: 谢谢亨里克提供的链接。我已经取得了一些进一步的进步。 我计算了将条形图居中的日期中点:

wtchange.data$date.midpoint <- wtchange.data$start.date +
(wtchange.data$end.date - wtchange.data$start.date)/2

然后计算用作条宽度的周期长度:

wtchange.data$period.length <- wtchange.data$end.date - wtchange.data$start.date

更新后的图形代码现在是:

ggplot(wtchange.data, aes(x = date.midpoint, y = wtchange)) +
  geom_bar(stat = "identity", color = "black", width = wtchange.data$period.length) +
  geom_errorbar(aes(ymin = wtchange-se, ymax = wtchange+se), width = 1)

enter image description here

剩下的唯一问题是一个地方的条之间仍然有一个小间隙。我猜这是由于 R 将日期差异计算四舍五入到最接近的天数的方式所致?

最佳答案

您是对的:结束日期和开始日期之间的差异的计算才是造成差距的原因。在计算宽度和中点时,我们需要使用numeric周期而不是difftime(请参见下面的解释)。

# length of periods, width of bars as numeric
df$width <- as.numeric(df$end.date - df$start.date) 

# mid-points
df$mid <- df$start.date + df$width / 2

# dates for breaks 
dates <- unique(c(df$start.date, df$end.date))

ggplot(df, aes(x = mid, y = wtchange)) +
  geom_bar(stat = "identity", color = "black", width = df$width) +
  geom_errorbar(aes(ymin = wtchange - se, ymax = wtchange + se), width = 1) +
  scale_x_date(breaks = dates)

enter image description here


对应的geom_rect代码:

# mid-points
df$mid <- df$start.date + as.numeric(df$end.date - df$start.date) / 2

# dates for breaks 
dates <- unique(c(df$start.date, df$end.date))

ggplot(df, aes(x = mid, y = wtchange)) +
  geom_rect(aes(xmin = start.date, xmax = end.date, ymin = 0, ymax = wtchange), color = "black") +
  geom_errorbar(aes(ymin = wtchange - se, ymax = wtchange + se), width = 1) +
  scale_x_date(breaks = dates)

使用geom_step对墨水的要求稍低:

# need to add an end date to the last period
df2 <- tail(df, 1)
df2$start.date <- df2$end.date
df2 <- rbind(df, df2)

# mid-points
df$mid <- df$start.date + as.numeric(df$end.date - df$start.date) / 2

ggplot() +
  geom_step(data = df2, aes(x = start.date, y = wtchange)) +
  geom_errorbar(data = df, aes(x = mid, ymin = wtchange - se, ymax = wtchange + se), width = 1) +
  scale_x_date(breaks = dates) +
  ylim(0, 16) +
  theme_bw()

enter image description here


关于“difftime问题”:

Date 类的值可以在内部表示为小数天(请参阅 ?Date?Ops.Date;尝试: Sys.Date() ; Sys.Date() + 0.5; Sys.Date() + 0.5 + 0.5)。但是,将 difftime 对象添加到 Date 时,difftime 对象将四舍五入到最近的一天(请参阅?Ops.Date 中的 x 参数)。

让我们使用开始日期 2015-04-15 和结束日期 2015-04-30 检查计算结果:

mid <- (as.Date("2015-04-30") - as.Date("2015-04-15")) / 2
mid
# Time difference of 7.5 days

str(mid)
# Class 'difftime'  atomic [1:1] 7.5
# ..- attr(*, "units")= chr "days"

# calculate the midpoint using the difftime object
as.Date("2015-04-15") + mid
# [1] "2015-04-23"

# calculating midpoint using numeric object yields another date...
as.Date("2015-04-15") + as.numeric(mid)
# [1] "2015-04-22"

# But is "2015-04-15" above in fact fractional, i.e. "2015-04-22 point 5"?
# Let's try and add 0.5
as.Date("2015-04-15") + as.numeric(mid) + 0.5
# [1] "2015-04-23"
# Yes.

因此,我们使用numeric 周期,而不是difftime 周期。

关于r - x 轴上以可变条形宽度作为日期范围的条形图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36134413/

相关文章:

r - R中的自引用嵌套函数?

r - 如何以编程方式告诉 ggplot 有多少个方面?

r - 使用季度日期格式缩放 x 轴

javascript - 如何将自定义悬停功能添加到 plotOutput 以便它可以用于许多绘图

r - 用 R 中的 latex 注释 ggplot2 人脸标签

r - 是否有 R 函数可以打印列名并将其导出到 Excel?

r - ggplot2 添加缩写指南

r - 如何交叉粘贴两个向量的所有组合(每个向量)?

r - 如何从 data.frame 中获取每一列作为 data.frame (而不是向量)?

r - 进行热图,水平/等高线图和六边形合并的方法