2014-12-04 4 views
0

Этот вопрос строится на How can i provide shades between dates on x axis in R plot? и How to align multiple ggplot2 plots and add shadows over all of them.Затенение много разных частей в ggplot2

Прежде чем я углубится в детали, я хочу сконденсировать количество кода, которое мне нужно было бы написать, чтобы затенять множество разных разделов. Я надеюсь, что смогу передать всю эту информацию в один кусок кода.

Вот мой MWE:

library(ggplot2) 
library(scales) 
set.seed(1) 
data <- data.frame(Date = seq(as.Date('2000-01-01'), 
        len= 23, by="1 day"), 
        Value = sample(1:50, 23, replace=TRUE)) 
rect1 <- data.frame(xmin=as.Date('2000-01-03 12:00:00'), 
        xmax=as.Date('2000-01-04 12:00:00'), 
        ymin=-Inf, 
        ymax=Inf) 
rect2 <- data.frame(xmin=as.Date('2000-01-10'), 
        xmax=as.Date('2000-01-11'), 
        ymin=-Inf, 
        ymax=Inf) 
rect3 <- data.frame(xmin=as.Date('2000-01-17 00:00:00'), 
        xmax=as.Date('2000-01-18 00:00:00'), 
        ymin=-Inf, 
        ymax=Inf) 
ggplot() + 
    geom_line(data=data, aes(x = Date, y = Value)) + 
    geom_rect(data = rect1, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha = 0.4) + 
    geom_rect(data = rect2, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha = 0.4) + 
    geom_rect(data = rect3, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha = 0.4) + 
    scale_x_date(breaks = date_breaks("1 day"), labels = date_format("%d")) 

Таким образом, я получаю сюжет с 3 различными затененных областей:

Plot of MWE

Имея 3 секции в тени не слишком плохо, но что если мне нужно затенять 100? Есть ли способ не определять 100 кадров данных, а затем добавлять все эти штрихи один за другим?

И, во-вторых, я хочу, чтобы мои оттенки были в середине значения. Но во всех трех спецификациях (rect1, rect2 и rect3) каждое затенение начинается со значения для этой даты и заканчивается значением для следующей даты. Любые советы о том, как это сделать?

ответ

3

Вы ближе, чем думаете!

Вместо того, чтобы создавать один кадр данных для каждого прямоугольника, вы можете просто создать единый фрейм данных, где каждая строка - это диапазон дат, который должен быть затенен. Ниже приведен пример одного примера данных вашего примера (с data, который совпадает с вашим).

dateRanges <- data.frame(
    from=as.Date(c('2000-01-03 12:00:00', '2000-01-10', '2000-01-17 00:00:00')), 
    to=as.Date(c('2000-01-04 12:00:00', '2000-01-11', '2000-01-18 00:00:00')) 
) 
ggplot() + geom_line(data=data, aes(x = Date, y = Value)) + 
    geom_rect(data = dateRanges, aes(xmin = from - 1, xmax = to, ymin = -Inf, ymax = Inf), alpha = 0.4) 

И полученное изображение:

plot with rectangles shaded

пара вещей, чтобы заметить:

  1. Использование xmin = from - 1 сдвига левой границы так, что затененный прямоугольник начинается до даты, указанной в from колонка.
  2. Я переименовал его с rect в dateRanges, чтобы показать, что вы действительно можете вытащить данные прямоугольника из любого кадра данных - он не должен быть так тесно связан с сюжетом, который вы будете делать (и вещами может быть проще отслеживать строку, если вы назовете dataframe более описательно).
  3. Также в вашем случае вам не нужны столбцы ymin и ymax в вашем фрейме данных, так как вы можете напрямую ссылаться на -Inf и Inf.

UPDATE

Это происходит со мной, что, если вам не нужны диапазоны переменной ширины, вы могли бы на самом деле просто использовать один столбец для кадра данных (importantDates = data.frame(Date=as.Date(c(...)))), а затем использовать xmin = Date - 1, Xmax = Дата + 1` в сюжете.

Более того, если бы это было уместно для вашей ситуации, вы могли бы даже генерировать фрейм данных importantDates на основе одного или нескольких столбцов исходных данных с чем-то вроде importantDates <- data[data$Value > 40,] (или что-то еще).

+0

Thanks @anandthakker Это работает. Один вопрос в вашей точке 1 - 'xmin = от -1' в эффекте оттенков 2 дня вместо одного. Что, если бы я хотел затенять только один день, но сдвиньте это так, чтобы он был сосредоточен в этот день. Например, для 03 января у меня будет панель, как у вас есть, но ваш барабан будет на половину размера и по-прежнему сосредоточен на 03 января. Фактически, я бы пошел с января 02 пополудни - 03 января. Другой ответ делает это, но можно ли это сделать без использования класса POSIXct? – bill999

+0

Выяснил это - используйте 'xmin = from - .5' и' xmax = from + .5'. – bill999

1

Вы можете иметь оттенок, нанесенный в середине, используя объекты POSIXct.

Вы можете включить любое количество оттенков, определяющих список, содержащий все координаты.

library(ggplot2) 
library(scales) 
set.seed(1) 
data <- data.frame(
    Date = as.POSIXct(seq(as.Date('2000-01-01'), len= 23, by="1 day")), 
    Value = sample(1:50, 23, replace=TRUE) 
) 

Вы можете определить вектор, содержащий все даты, начиная с, считая, что ширина полосы всегда один день. Кроме того, вы можете определить кадр данных, содержащий две даты, и использовать apply или dlply (from plyr).

vectorDates <-seq(
    as.POSIXct('2000-01-03 12:00:00'), 
    as.POSIXct('2000-01-20 12:00:00'), 
    length.out = 10 
) 
list_geom_rect <- lapply(vectorDates, function(date1) 
{ 
    date2 <- date1 + 3600 * 24 
    rect <- data.frame(
    xmin = date1, xmax = date2, 
    ymin = -Inf, ymax = Inf 
) 
    geom_rect(
    data = rect, 
    mapping = aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), 
    alpha = 0.4 
) 
}) 

Теперь вы можете построить участок и добавить все полосы.

p <- ggplot() + geom_line(data=data, aes(x = Date, y = Value)) 
    for(geom in list_geom_rect){ 
     p <- p + geom 
    } 
p 
Смежные вопросы