如何在图上添加平均间隔

时间:2018-06-03 17:53:41

标签: r plot

我有一个数据集,其中包含从2018-04-22T11:48:53结束2018-04-22T12:03:24开始的日期。每个时间戳都有自己的价值。我需要创建一个带data.frame的函数,并根据该函数绘制一个带有实际值和每个区间平均值的图。

1 个答案:

答案 0 :(得分:2)

OP要求创建一个采用data.frame的函数,并根据该函数绘制每个区间的实际值和平均值的图。

将使用data.table进行聚合,scales创建“漂亮”区间,ggplot2进行绘图,以及checkmate用于检查输入参数:

plot_avg <- function(DF, x_arg, y_arg, interval_width, show_avg = NULL) {
  # check arguments
  checkmate::assert_data_frame(DF, min.rows = 1L, min.cols = 2L, 
                               col.names = "strict")
  checkmate::assert_string(x_arg, min.chars = 1L)
  checkmate::assert_string(y_arg, min.chars = 1L)
  checkmate::assert_subset(c(x_arg, y_arg), names(DF))
  checkmate::assert_number(interval_width, lower = .Machine$double.xmin)
  checkmate::assert_character(show_avg, null.ok = TRUE)
  checkmate::assert_subset(show_avg, c("segm", "step", ""))
  # load required packages
  library(data.table)
  library(ggplot2)
  # compute averages
  breaks <- scales::fullseq(range(DF[[x_arg]]), interval_width)
  aggDT <- as.data.table(DF)[
    , .(avg = mean(get(y_arg))), 
    by = .(start  = breaks[cut(get(x_arg), breaks, right = FALSE, labels = FALSE)])]
  # start plotting
  g <- ggplot(DF) + aes_string(x_arg, y_arg) +
    geom_point(color = "blue") + 
    {if (length(breaks) < 30) scale_x_continuous(breaks = breaks)} +
    theme_bw()
  if ("segm" %in% show_avg) 
    g <- g + geom_segment(aes(x = start, xend = start + interval_width, 
                              y = avg, yend = avg), aggDT)
  if ("step" %in% show_avg) 
    g <- g + geom_step(aes(start, avg), aggDT, linetype = "dashed")
  # return plot object
  return(g)
}

使用如下所述创建的样本数据集,我们可以创建不同的图。

仅数据点:

plot_avg(DT, "sec", "value", 60L)

enter image description here

将平均值作为水平线段:

plot_avg(DT, "sec", "value", 60L, "segm")

enter image description here

将平均值作为水平线段加上步骤

plot_avg(DT, "sec", "value", 60L, c("segm", "step"))

enter image description here

间隔宽度可以改变:

plot_avg(DT, "sec", "value", 20L, c("segm", "step"))

enter image description here

数据

OP尚未提供任何可公开访问的样本数据。所以,我必须编写自己的样本数据集:

library(data.table)
secs <- seq(lubridate::ymd_hms("2018-04-22T11:48:53"), 
            lubridate::ymd_hms("2018-04-22T12:03:24"), 
            by = "sec")
n_secs <- length(secs)
n_row <- as.integer(n_secs / 10)
set.seed(0)
DT <- data.table(times = sort(sample(secs, n_row)))
DT[, sec := as.integer(times - min(times))]
f <- 2*pi/n_secs
DT[, value := cos(f*sec) + sin(2*f*sec) + 0.1 * rnorm(.N)]