2016-03-21 1 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) я могу использовать только одну переменную (start.date в этом примере) для оси x, но мне действительно нужно чтобы как-то использовать как start.date, так и end.date, чтобы разграничить ширину полосы, соответствующую каждому периоду. График должен выглядеть следующим образом (нарисованный в Paint): enter image description here

Вторичная проблема состоит в том, что стержни должны касаться без пробелов, но я не уверен, если это вообще возможно, учитывая, что стержни должны быть разной ширины, поэтому вы не можете установить ширину полосы для всех баров. Можно ли установить ширину для каждого бара вручную?


Edit: Спасибо Хенрика за ссылки. Я сделал некоторый дальнейший прогресс. I рассчитываются середины даты для центрирования полосы по адресу:

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

Единственная проблема, остающаяся i что все еще есть небольшой промежуток между барами в одном месте. Думаю, это связано с тем, как расписание разницы между датами 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 равен округленный ближайший целый день (см. x аргумент в ?Ops.Date).

Давайте проверим расчеты, используя дату 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 периода.

Смежные вопросы