R + ggplot: временные ряды с событиями



Я новичок в R/ggplot. Я хотел бы создать график geom_line непрерывного переменного временного ряда, а затем добавить слой, состоящий из событий. Непрерывная переменная и ее временные метки хранятся в одних данных.фрейм, события и их временные метки хранятся в других данных.рамка.



что я действительно нравится делать что-то вроде диаграмм на finance.google.com в них временной ряд-это цена акций и есть" флаги " для обозначения новостей-событий. Я на самом деле не рисую финансовые вещи, но тип графика похож. Я пытаюсь построить визуализации данных файла журнала. Вот пример что я имею в виду...



google chart with events



Если целесообразно (?), Я хотел бы использовать отдельные данные.кадры для каждого слоя (один для непрерывных переменных наблюдений, другой для событий).



после некоторых проб и ошибок это примерно так же близко, как я могу получить. Здесь я использую пример данных из наборов данных, которые поставляются с ggplot. "экономика "содержит некоторые данные временных рядов, которые я хотел бы построить, а" президентский " содержит несколько событий (президентские выборы).



library(ggplot2)
data(presidential)
data(economics)

presidential <- presidential[-(1:3),]
yrng <- range(economics$unemploy)
ymin <- yrng[1]
ymax <- yrng[1] + 0.1*(yrng[2]-yrng[1])

p2 <- ggplot()
p2 <- p2 + geom_line(mapping=aes(x=date, y=unemploy), data=economics , size=3, alpha=0.5)
p2 <- p2 + scale_x_date("time") + scale_y_continuous(name="unemployed [1000's]")
p2 <- p2 + geom_segment(mapping=aes(x=start,y=ymin, xend=start, yend=ymax, colour=name), data=presidential, size=2, alpha=0.5)
p2 <- p2 + geom_point(mapping=aes(x=start,y=ymax, colour=name ), data=presidential, size=3)
p2 <- p2 + geom_text(mapping=aes(x=start, y=ymax, label=name, angle=20, hjust=-0.1, vjust=0.1),size=6, data=presidential)
p2


my attempt



вопросы:




  • Это нормально для очень редких событий, но если есть кластер из них (как часто бывает в файле журнала), он становится грязным. Есть ли какой-то метод, который я могу использовать, чтобы аккуратно отображать кучу событий, происходящих за короткий промежуток времени? Я думал о position_jitter, но это мне было очень трудно зайти так далеко. Google charts складывает эти "флаги" событий друг на друга, если их много.


  • мне на самом деле не нравится вставлять данные о событиях в том же масштабе, что и дисплей непрерывного измерения. Я бы предпочел поместить его в facet_grid. Проблема в том, что все грани должны быть получены из одних и тех же данных.кадр (не уверен, что это правда). Если да, то это также кажется не идеальным (или, может быть, я просто пытаюсь избежать использования изменить форму?)


744   3  

3 ответов:

насколько мне нравится ответ @JD Long, я поставлю тот, который находится только в R/ggplot2.

подход состоит в том, чтобы создать второй набор данных событий и использовать его для определения позиций. Начиная с того, что у @Angelo было:

library(ggplot2)
data(presidential)
data(economics)

извлеките данные события (президентские) и преобразуйте их. Вычислить baseline и offset в качестве фракций экономических данных он будет нанесен на график. Установите нижнюю часть (ymin) к базовой линии. Вот тут-то и начинается самое сложное. Мы нужно уметь смещения меток, если они находятся слишком близко друг к другу. Поэтому определите расстояние между соседними метками (предполагается, что события отсортированы). Если это меньше некоторой суммы (я выбрал около 4 лет для этой шкалы данных), то обратите внимание, что эта метка должна быть выше. Но он должен быть выше, чем тот, что после него, так что используйте rle чтобы получить длину TRUE ' s (то есть должно быть выше) и вычислить вектор смещения, используя это (каждая строка TRUE должен отсчитывать от своего длина до 2, то FALSEs просто со смещением 1). Используйте это для определения верхней части баров (ymax).

events <- presidential[-(1:3),]
baseline = min(economics$unemploy)
delta = 0.05 * diff(range(economics$unemploy))
events$ymin = baseline
events$timelapse = c(diff(events$start),Inf)
events$bump = events$timelapse < 4*370 # ~4 years
offsets <- rle(events$bump)
events$offset <- unlist(mapply(function(l,v) {if(v){(l:1)+1}else{rep(1,l)}}, l=offsets$lengths, v=offsets$values, USE.NAMES=FALSE))
events$ymax <- events$ymin + events$offset * delta

положить это вместе в сюжет:

ggplot() +
    geom_line(mapping=aes(x=date, y=unemploy), data=economics , size=3, alpha=0.5) +
    geom_segment(data = events, mapping=aes(x=start, y=ymin, xend=start, yend=ymax)) +
    geom_point(data = events, mapping=aes(x=start,y=ymax), size=3) +
    geom_text(data = events, mapping=aes(x=start, y=ymax, label=name), hjust=-0.1, vjust=0.1, size=6) +
    scale_x_date("time") +  
    scale_y_continuous(name="unemployed \[1000's\]")

вы могли бы грань, но это сложно с разных шкал. Другой подход заключается в составлении двух графиков. Есть некоторые дополнительные манипуляции, которые необходимо сделать, чтобы убедиться, что графики имеют одинаковый X-диапазон, чтобы все метки вписывались в нижний участок и устраняли ось x на верхнем участке.

xrange = range(c(economics$date, events$start))

p1 <- ggplot(data=economics, mapping=aes(x=date, y=unemploy)) +
    geom_line(size=3, alpha=0.5) +
    scale_x_date("", limits=xrange) +  
    scale_y_continuous(name="unemployed [1000's]") +
    opts(axis.text.x = theme_blank(), axis.title.x = theme_blank())

ylims <- c(0, (max(events$offset)+1)*delta) + baseline
p2 <- ggplot(data = events, mapping=aes(x=start)) +
    geom_segment(mapping=aes(y=ymin, xend=start, yend=ymax)) +
    geom_point(mapping=aes(y=ymax), size=3) +
    geom_text(mapping=aes(y=ymax, label=name), hjust=-0.1, vjust=0.1, size=6) +
    scale_x_date("time", limits=xrange) +
    scale_y_continuous("", breaks=NA, limits=ylims)

#install.packages("ggExtra", repos="http://R-Forge.R-project.org")
library(ggExtra)

align.plots(p1, p2, heights=c(3,1))

теперь мне нравится ggplot так же, как и следующий парень, но если вы хотите сделать диаграммы типа Google Finance, почему бы просто не сделать это с помощью Google graphics API?!? Вы будете любить это:

install.packages("googleVis")
library(googleVis)

dates <- seq(as.Date("2011/1/1"), as.Date("2011/12/31"), "days")
happiness <- rnorm(365)^ 2
happiness[333:365] <- happiness[333:365]  * 3 + 20
Title <- NA
Annotation <- NA
df <- data.frame(dates, happiness, Title, Annotation)
df$Title[333] <- "Discovers Google Viz"
df$Annotation[333] <- "Google Viz API interface by Markus Gesmann causes acute increases in happiness."

### Everything above here is just for making up data ### 
## from here down is the actual graphics bits        ###
AnnoTimeLine  <- gvisAnnotatedTimeLine(df, datevar="dates",
                                       numvar="happiness", 
                                       titlevar="Title", annotationvar="Annotation",
                                       options=list(displayAnnotations=TRUE,
                                                    legendPosition='newRow',
                                                    width=600, height=300)
                                       )
# Display chart
plot(AnnoTimeLine) 
# Create Google Gadget
cat(createGoogleGadget(AnnoTimeLine), file="annotimeline.xml")

и он производит эту фантастическую графику:

enter image description here

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

конечным результатом является график, на который можно перетащить курсор. На графиках отображаются интересующие данные:

enter image description here

вот код для создания ggplot:

# load data    
data(presidential)
data(economics)

# events of interest
events <- presidential[-(1:3),]

# strip year from economics and events data frames
economics$year = as.numeric(format(economics$date, format = "%Y")) 

# use dplyr to summarise data by year
#install.packages("dplyr")
library(dplyr)
econonomics_mean <- economics %>% 
  group_by(year) %>% 
  summarise(mean_unemployment = mean(unemploy))

# add president terms to summarized data frame as a factor
president <- c(rep(NA,14), rep("Reagan", 8), rep("Bush", 4), rep("Clinton", 8), rep("Bush", 8), rep("Obama", 7))
econonomics_mean$president <- president

# create ggplot
p <- ggplot(data = econonomics_mean, aes(x = year, y = mean_unemployment)) +
  geom_point(aes(color = president)) +
  geom_line(alpha = 1/3)

это займет всего одну строку кода, чтобы сделать ggplot в plotly объект.

# make it interactive!
#install.packages("plotly")
library(plotly)
ggplotly(p)

Comments

    Ничего не найдено.