web-dev-qa-db-ja.com

R + ggplot:イベントの時系列

私はR/ggplotの初心者です。連続可変時系列のgeom_lineプロットを作成してから、イベントで構成されるレイヤーを追加します。連続変数とそのタイムスタンプは1つのdata.frameに保存され、イベントとそのタイムスタンプは別のdata.frameに保存されます。

本当にしたいことは、finance.google.comのグラフのようなものです。それらでは、時系列は株価であり、ニュースイベントを示す「フラグ」があります。私は実際には金融関連のものをプロットしていませんが、グラフのタイプは似ています。ログファイルデータの視覚化をプロットしようとしています。これが私の意味の例です...

google chart with events

推奨される場合(?)、各レイヤーに個別のdata.framesを使用します(1つは連続変数の観測用、もう1つはイベント用)。

試行錯誤の後、これは私が得ることができる限り近いです。ここでは、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を考えていましたが、これを達成するのは本当に大変でした。グーグルチャートは、これらのイベント「フラグ」が多数ある場合、それらを積み重ねます。

  • 実際には、連続測定表示と同じスケールでイベントデータを貼り付けるのは好きではありません。私はそれをfacet_gridに入れたいと思います。問題は、すべてのファセットが同じdata.frameから供給される必要があることです(これが当てはまるかどうかはわかりません)。もしそうなら、それも理想的ではないようです(あるいは私は単に形を変えるのを避けようとしているだけですか?)

59
Angelo

@JD Longの答えが好きなだけ、R/ggplot2にあるものを入れます。

アプローチは、イベントの2番目のデータセットを作成し、それを使用して位置を決定することです。 @Angeloが持っていたものから始めます:

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

イベント(プレジデンシャル)データを引き出して変換します。 baselineoffsetを、プロットする経済データの分数として計算します。下(ymin)をベースラインに設定します。ここがトリッキーな部分です。ラベルが近すぎる場合は、ラベルをずらす必要があります。したがって、隣接するラベル間の間隔を決定します(イベントがソートされていると仮定します)。ある量より少ない場合(このデータスケールでは約4年を選択しました)、そのラベルを高くする必要があることに注意してください。ただし、それよりも後の値よりも大きい必要があるため、rleを使用してTRUEの長さを取得し(つまり、より長くする必要があります)、それを使用してオフセットベクトルを計算します(各文字列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\]")

ファセットにすることもできますが、スケールが異なるとトリッキーです。別のアプローチは、2つのグラフを作成することです。プロットが同じ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))

36
Brian Diggs

今、私は次の人と同じくらいggplotが好きですが、Google Financeタイプのグラフを作成したい場合は、Googleグラフィック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

83
JD Long

Plotlyは、ggplotをインタラクティブにする簡単な方法です。イベントを表示するには、色などの美的要素として表示できる要素にそれらを強制します。

最終結果は、カーソルをドラッグできるプロットです。プロットは目的のデータを表示します。

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オブジェクトにするために必要なコードは1行だけです

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