如何在ggplot2中绘制平滑的摘要统计数据

时间:2018-01-08 06:10:16

标签: r ggplot2

我无法阐明这个问题。我有一个日常收入和支出数年的数据集。我一直在尝试一些方法,所以现在有很多日期列。

> str(df)
'data.frame':   3047 obs. of  8 variables:
 $ Date             : Factor w/ 1219 levels "2014-05-06T00:00:00.0000000",..: 6 9 2 3 4 6 10 11 13 14 ...
 $ YearMonthnumber  : Factor w/ 44 levels "2014/05","2014/06",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ cat              : Factor w/ 10 levels "Account Adjustment",..: 1 2 3 3 3 3 3 3 3 3 ...
 $ Value            : num  2.2 277.7 20 14.1 6.8 ...
 $ Income_or_expense: Factor w/ 2 levels "Expense","Income": 1 1 1 1 1 1 1 1 1 1 ...
 $ ddate            : Date, format: "2014-05-16" "2014-05-19" "2014-05-12" "2014-05-13" ...
 $ monthly          : Date, format: "2014-05-01" "2014-05-01" "2014-05-01" "2014-05-01" ...

基本上我想绘制的是:

  • 每个月收入的总和以及每个月费用的总和(即价值列),其中类别(cat)不是"转移",由income_or_expense着色
  • 通过这些摘要点绘制平滑线。

我可以做第一步,但不能做两步。这就是我所拥有的:

ggplot(data = subset(df, cat!="Transfer"), aes(x = monthly, y= Value, colour = Income_or_expense)) +
  stat_summary(fun.y = sum, geom = "point") +
  scale_x_date(labels = date_format("%Y-%m"))

如何为这些生成的摘要统计信息添加平滑的geom?

编辑:如果我添加+ stat_summary(fun.y = sum, geom = "smooth"),结果是折线图,而不是平滑模型。如果我在没有fun.y = sum的情况下添加它,则平滑的行基于每日值,而不是每月聚合

感谢。

1 个答案:

答案 0 :(得分:3)

您可以先按月汇总数据,然后在汇总数据上运行geom_smooth。我为这个例子创建了一些虚假的时间序列数据。

library(tidyverse)  
library(lubridate)

# Fake data
set.seed(2)
dat = data.frame(value = c(arima.sim(list(order = c(1,1,0), ar = 0.7), n = 364),
                           arima.sim(list(order = c(1,1,0), ar = 0.7), n = 364)) + 100,
                 IE = rep(c("Income","Expense"), each=365),
                 date = rep(seq(as.Date("2015-01-01"), as.Date("2015-12-31"), by="day"), 2))

现在我们按月和情节求和。我已经将实际每月总和的积分与平滑线进行比较:

ggplot(dat %>% group_by(IE, month=month(date, label=TRUE)) %>% 
         summarise(value=sum(value)), 
       aes(month, value, colour=IE, group=IE)) +
  geom_smooth(se=FALSE, span=0.75) +  # span=0.75 is the default
  geom_point() +
  expand_limits(y=0) +
  theme_classic()

enter image description here

我对时间序列分析并不熟悉,但似乎更好的方法是计算每个每日价值所代表的月收入和费用率,然后通过它运行更顺畅。这样你就不会总结出底层数据的变化。在下面的图中,我已经包含了各个点,因此您可以将它们与更平滑的线进行比较。

ggplot(dat %>% group_by(IE, month=month(date, label=TRUE)) %>% 
         mutate(value = value * n()), 
       aes(date, value, colour=IE)) +
  geom_smooth(se=FALSE, span=0.75) +
  geom_point(alpha=0.3, size=1) +
  expand_limits(y=0) +
  theme_classic()

enter image description here

您还可以绘制30天滚动总和,避免将数据分组到任意时间段。我再次列出了每日收入和费用率的点数。

library(xts)

ggplot(dat %>% group_by(IE) %>% 
         mutate(rolling_sum = rollsum(value, k=30, align="center", na.pad=TRUE),
                value = value * 30), 
       aes(date, colour=IE)) +
  geom_line(aes(y=rolling_sum), size=1) +
  geom_point(aes(y=value), alpha=0.2, size=1) +
  expand_limits(y=0) +
  theme_classic()

enter image description here