こういう、複数のデータ系列を持つ時系列データがあるとします。で、このデータを使って積み重ねグラフを描きたいとします。
library(dplyr) library(lubridate) set.seed(1) d <- data_frame(time = seq(ymd_h(2015042400), ymd_h(2015042401), by = "min"), value1 = 10 + runif(length(time)), value2 = 10 + runif(length(time)), value3 = 10 + runif(length(time)))
やることはひとつ。tidyにしてggplot2を使うだけです。単純明快です。
library(tidyr) library(ggplot2) library(gridExtra) d_tidy <- d %>% gather(type, value, -time) %>% arrange(time) p <- ggplot(d_tidy, aes(x = time, y = value)) p1 <- p + geom_line(aes(colour = type)) + ylim(c(0, NA)) p2 <- p + geom_area(aes(fill = type), position = "stack") grid.arrange(p1, p2)
現実は甘くない
しかし、たとえば一定間隔でセンサーから値を取ってDBに入れる、みたいなパターンを想像すると、こんなにキレイに同時刻にデータを観測できているとは限りません。現実に即して、timeにずれを付け加えてみます。
set.seed(1) d_fuzzy <- d_tidy %>% mutate(time = time + seconds(round(runif(n(), min = -15, max = 15))))
で、これをさっきと同じノリで積み重ねてみると、、
p <- ggplot(d_fuzzy, aes(x = time, y = value)) p1 <- p + geom_line(aes(colour = type)) + ylim(c(0, NA)) p2 <- p + geom_area(aes(fill = type), position = "stack") grid.arrange(p1, p2)
なんと、積み重なってません。あれ、postion = "stack"
を忘れてる??と思って二度見しましたが、そんなことはありません。
積み重ねグラフは、X軸の値が完全に同じじゃないと積み重ねられないので、少しでもずれがあるとダメです。
データを補間する
そんなときはapprox()
でデータを補完するといいっぽいです。approx()
はxout
というパラメータで補間してほしい場所を指定できます。ここに、きれいな刻みの時刻を指定しておきます。
補間はデータ系列ごとにやらないとだめなので、いちどsplit()
しないとだめそうです。
d_split <- split(d_fuzzy, d_fuzzy$type) tics <- seq(ymd_h(2015042400), ymd_h(2015042401), by = "min") res <- list() for(t in names(d_split)) { tmp <- d_split[[t]] res[[t]] <- as_data_frame(approx(x = tmp$time, y = tmp$value, xout = tics, rule = 2)) res[[t]]$type <- t } d_tidy_at_last <- bind_rows(res) p <- ggplot(d_tidy_at_last, aes(x = x, y = y)) p1 <- p + geom_line(aes(colour = type)) + ylim(c(0, NA)) p2 <- p + geom_area(aes(fill = type), position = "stack") grid.arrange(p1, p2)
うーん、こんな感じでいいんでしょうか。。
もうちょっときれいな書き方をだれか教えてください。
参考にしたサイト
大仏様ありがとうございます。