2016-03-21 68 views
2

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

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)时,对于x轴,我只能使用一个变量(本例中为start.date),但我确实需要以某种方式使用start.dateend.date来限定对应于每个周期的条宽度。该图应该看起来像这样(在Paint中绘制): enter image description here

第二个问题是条纹应该没有间隙地接触,但我不确定它是否可能,因为条纹必须是不同的宽度,所以你不能为所有酒吧设置一个酒吧宽度。是否可以手动设置每个条的宽度?


编辑: 谢谢Henrik的链接。我取得了一些进展。 余计算的日期中点在定心杆:

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将日期差异计算到最近的天数的方式?

回答

1

你是对的:它是计算结束和开始日期之间的差异,这是差距的原因。在计算宽度和中点时,我们需要使用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时期。