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

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

вопросы:
Это нормально для очень редких событий, но если есть кластер из них (как часто бывает в файле журнала), он становится грязным. Есть ли какой-то метод, который я могу использовать, чтобы аккуратно отображать кучу событий, происходящих за короткий промежуток времени? Я думал о position_jitter, но это мне было очень трудно зайти так далеко. Google charts складывает эти "флаги" событий друг на друга, если их много.
мне на самом деле не нравится вставлять данные о событиях в том же масштабе, что и дисплей непрерывного измерения. Я бы предпочел поместить его в facet_grid. Проблема в том, что все грани должны быть получены из одних и тех же данных.кадр (не уверен, что это правда). Если да, то это также кажется не идеальным (или, может быть, я просто пытаюсь избежать использования изменить форму?)
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")и он производит эту фантастическую графику:
Plotlyэто простой способ сделать ggplots интерактивными. Чтобы отобразить события, принудите их к факторам, которые могут отображаться как эстетические, например цвет.конечным результатом является график, на который можно перетащить курсор. На графиках отображаются интересующие данные:
вот код для создания 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