【问题标题】:Use zoo read and split a data frame over a column使用动物园读取并在列上拆分数据框
【发布时间】:2013-02-08 18:38:21
【问题描述】:

我有一个表格,其中包含对restaurants(由 ID 标识)的分数的观察。变量mean是在以每天为中心的一周窗口内(即从前3天到后3天)收到的评论的平均评分,变量count是在同一窗口中收到的评论数(请参阅下面的代码以获取我的数据框随机生成的样本的dput)。

我有兴趣查看那些在任一变量中都包含大幅峰值的餐厅(比如突然间,他们的平均评分上升了很多,或者突然下降了)。对于那些餐馆,我想通过绘制分布来调查发生了什么(我有很多餐馆,所以我不能手动完成,我必须限制我的域以进行半手动检查)。

另外,由于我的数据是每天的,我希望它不那么精细。特别是,我想用一个值对给定月份的所有评级或计数进行平均。

我认为 zoo 应该帮助我做得很好:鉴于示例中的数据框,我认为我可以将其转换为 zoo 时间序列,该时间序列以我想要的方式聚合并通过使用以下方式拆分我想要的方式:

z <- read.zoo(df, split = "restaurantID", 
       format = "%m/%d/%Y", index.column = 2, FUN = as.yearmon, aggregate = mean)

但是,在 restaurantID 上拆分不会产生预期的结果。我得到的是很多 NA:

     mean.1006054 count.1006054 mean.1006639 count.1006639 mean.1006704 count.1006704 mean.1007177 count.1007177
Lug 2004           NA            NA           NA            NA           NA            NA           NA            NA
Ago 2004           NA            NA           NA            NA           NA            NA           NA            NA
Nov 2004           NA            NA           NA            NA           NA            NA           NA            NA
Gen 2005           NA            NA           NA            NA           NA            NA           NA            NA
Feb 2005           NA            NA           NA            NA           NA            NA           NA            NA
Mar 2005           NA            NA           NA            NA           NA            NA           NA            NA
         mean.1007296 count.1007296 mean.1007606 count.1007606 mean.1007850 count.1007850 mean.1008272 count.1008272
Lug 2004           NA            NA           NA            NA           NA            NA           NA            NA
Ago 2004           NA            NA           NA            NA           NA            NA           NA            NA
Nov 2004           NA            NA           NA            NA           NA            NA           NA            NA
Gen 2005           NA            NA           NA            NA           NA            NA           NA            NA
Feb 2005           NA            NA           NA            NA           NA            NA           NA            NA
Mar 2005           NA            NA           NA            NA           NA            NA           NA            NA

请注意,如果我不在 restaurantID 列上拆分它,它会起作用。

df$website <- NULL
> z <- read.zoo(df, format = "%m/%d/%Y", index.column = 2, FUN = as.yearmon, aggregate = mean)
> head(z)
         restaurantID     mean count
Lug 2004      1418680 3.500000     1
Ago 2004      1370457 5.000000     1
Nov 2004      1324645 4.333333     1
Gen 2005      1425933 1.920000     1
Feb 2005      1315289 3.000000     1
Mar 2005      1400577 2.687500     1

另外,plot.zoo(z) 有效,但生成的图表对我当然没有任何意义。

我的问题是:

1) 我如何过滤在任一列中具有较高“月-月”峰值的餐厅?

2) 如何在 restaurantID 上拆分并仅绘制此类餐厅的时间​​序列?

DATA HERE (wouldn't fit SO's word limit)

【问题讨论】:

  • +1 用于包含数据。
  • 输入有 1000 行,因此输入的均值和计数列由 2 * 1000 = 2000 个数字组成。 zoo 对象将有 63 个月的每一行和 347 个餐厅 ID 中的每一个的 2 列,因此如果您尝试将 2000 个数字放入具有 63 * 2 = 347 = 43722 个条目的矩阵中,那么这些条目将主要是 NA。
  • 快速查找餐厅变量变化的方法:ddply(df, .(restaurantID), function(x) cbind(delta_mean = max(x$mean) - min(x$mean), delta_count = max(x$count) - min(x$count)))
  • @GaryWeissman:我想查看“按月”的最大增量,这正是您绘制它时会看到的最高峰值。您的解决方案为我提供了 all 值之间的最大增量。
  • @Tex 修改后的方法贴在下面。

标签: r time-series zoo


【解决方案1】:

试试:

# helper function to calculate change per time interval in a sequence
difflist <- function(v) {rr <- 0; for (i in 2:length(v)) {rr <- c(rr, v[i] - v[i-1])}; return(rr) }

# make center as dates
df$center <- as.Date(df$center,format='%m/%d/%Y')

# sort data frame in time order
df <- df[order(df$restaurantID, df$center),]

# now calculate the change in each column
deltas <- ddply(df, .(restaurantID), function(x) {cbind(center = x$center, delta_mean = difflist(x$mean), delta_count = difflist(x$count)) } )

# filter out only the big spikes
deltas_big <- subset(deltas, delta_mean > 2 | delta_count > 3)

# arrange the data
delta_melt <- melt(deltas_big,id.vars=c('restaurantID','center'))

# now plot by time
ggplot(delta_melt, aes(x=center,y=value,color=variable)) + geom_point()

【讨论】:

  • 这不是我想要的 :-( 这样做并不能让我真正看到何时发生了突然的变化,因为我丢失了有关实际日期的信息。此外,还有没有每月汇总,这意味着数据太多。我得到的图表没有任何意义。img171.imageshack.us/img171/2820/plotzoom.png我什至不知道什么餐厅有尖峰,这有点整点
【解决方案2】:

开发了 robfilter r 包,用于过滤时间序列数据,以基于稳健的统计方法挑选出异常值,以进行时间序列分析。您可以使用 adore.filter 函数将模式拟合到数据中,然后选择远离信号的异常值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-28
    • 2014-11-15
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 2020-11-24
    • 2014-07-22
    • 2018-01-21
    相关资源
    最近更新 更多