2013-03-01 56 views
5

我对R相当陌生,我试图用aggregate对数据框,每个主题和数据集中的每个指标执行一些时间序列整形。这工作很好,但我发现结果不是一个非常容易使用的格式。我希望能够将结果转换回原始数据帧的相同格式。R聚合函数的结果平展/非规范化

使用虹膜数据集为例:

# Split into two data frames, one for metrics, the other for grouping 
iris_species = subset(iris, select=Species) 
iris_metrics = subset(iris, select=-Species) 
# Compute diff for each metric with respect to its species 
iris_diff = aggregate(iris_metrics, iris_species, diff) 

我只是用diff,以说明我塑造的时间序列的函数,所以我得到一个时间序列可能不同的长度为结果并且绝对不是单个总值(例如平均值)。

我想转换结果,这似乎是一个矩阵,它具有列表值单元格到原始“平坦”数据框。

我主要关心如何管理这个结果从aggregate结果,但我会很好的解决方案,在plyrreshape做任何事情。

+0

你在谈论时代系列..你举个基于虹膜的例子吗?!!你聚合使用差异?理由是什么?它会更好地使用时间序列软件包(动物园,xts,..)之一!真的我不明白你想要做什么(我至少读了3次你的问题) – agstudy 2013-03-01 23:21:28

+1

@agstudy,我*想*这个问题与'aggregate'的行为有点关系,如果你给它一个像'summary'或'fivenum'或其他可以返回多个列的函数。在这种情况下,结果是*看起来像多列data.frame,但实际上是一个'matrix'作为'data.frame'中的一列。因此,一个'do.call(data.frame,...)'应该能够“平坦”输出。 – A5C1D2H2I1M1N2O1R2T1 2013-03-02 09:54:10

+0

@AnandaMahto谢谢。我明白你的观点。 – agstudy 2013-03-02 19:39:08

回答

2

正如您所知,aggregate一次只能处理一列。单值预期,并且奇怪的事情发生,如果你从1

返回长度不同的向量可以与by拆分这件事来获取数据(比在iris更少的行),并把它重新走到一起:

b <- by(iris_metrics, iris_species, FUN=function(x) diff(as.matrix(x))) 
do.call(rbind, lapply(names(b), function(x) data.frame(Species=x, b[[x]]))) 

diff(as.matrix)作为本你想要做什么的矩阵(而不是数据帧)。关键是该函数返回的行数不同于iris中的每个Species

2

我可以在这种情况下想到的最好的办法是data.table

require(data.table) 
dt <- data.table(iris, key="Species") 
dt.out <- dt[, lapply(.SD, diff), by=Species] 

如果你想有一个plyr解决方案,那么这个想法基本上是相同的。按Species拆分并将diff应用于每列。

​​
+0

请问最低选民请解释原因,以便我可以尝试纠正它? – Arun 2013-03-05 18:57:39

1

如果你想回到某种形式的一阶差分向量与相同长度的输入向量,你应该用AVE和一个匿名函数这样做。由于diff返回不同长度的向量,因此需要使用NA(或您选择的标记)对其进行扩展。

iris_diff = lapply(iris_metrics, 
     function(xx) ave(xx, iris_species, FUN=function(x) c(NA, diff(x))) ) 
str(iris_diff) 
#-------------- 
List of 4 
$ Sepal.Length: num [1:150] NA -0.2 -0.2 -0.1 0.4 ... 
$ Sepal.Width : num [1:150] NA -0.5 0.2 -0.1 0.5 0.3 -0.5 0 -0.5 0.2 ... 
$ Petal.Length: num [1:150] NA 0 -0.1 0.2 -0.1 ... 
$ Petal.Width : num [1:150] NA 0 0 0 0 0.2 -0.1 -0.1 0 -0.1 ... 

如果你希望作为一个数据帧,只需在它周围包装data.frame。而这将是一个好主意,包括原来的分组载体:

iris_diff <- data.frame(Species= iris_species, iris_diff) 
str(iris_diff) 
#------ 
'data.frame': 150 obs. of 5 variables: 
$ Species  : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ... 
$ Sepal.Length: num NA -0.2 -0.2 -0.1 0.4 ... 
$ Sepal.Width : num NA -0.5 0.2 -0.1 0.5 0.3 -0.5 0 -0.5 0.2 ... 
$ Petal.Length: num NA 0 -0.1 0.2 -0.1 ... 
$ Petal.Width : num NA 0 0 0 0 0.2 -0.1 -0.1 0 -0.1 ... 
1

这就是我所理解的你的问题:根据您目前的使用aggregate的方法,你会得到“Sepal.Length”的结果matrix ,“Sepal.Width”等。

> str(iris_diff) 
'data.frame': 3 obs. of 5 variables: 
$ Species  : Factor w/ 3 levels "setosa","versicolor",..: 1 2 3 
$ Sepal.Length: num [1:3, 1:49] -0.2 -0.6 -0.5 -0.2 0.5 ... 
$ Sepal.Width : num [1:3, 1:49] -0.5 0 -0.6 0.2 -0.1 0.3 -0.1 -0.8 -0.1 0.5 ... 
$ Petal.Length: num [1:3, 1:49] 0 -0.2 -0.9 -0.1 0.4 ... 
$ Petal.Width : num [1:3, 1:49] 0 0.1 -0.6 0 0 0.2 0 -0.2 -0.3 0 ... 

但是,在您的控制台,显示作为什么看起来data.frame 197列。

要将“iris_diff”转换为具有197列的data.frame。这里是你如何能做到这一点与现有的输出(一招我从@詹姆斯,here拿起SO):

do.call(data.frame, iris_diff) 

以下是输出的前几行的时候,我们认为,行动的str

> str(do.call(data.frame, iris_diff)) 
'data.frame': 3 obs. of 197 variables: 
$ Species  : Factor w/ 3 levels "setosa","versicolor",..: 1 2 3 
$ Sepal.Length.1 : num -0.2 -0.6 -0.5 
$ Sepal.Length.2 : num -0.2 0.5 1.3 
$ Sepal.Length.3 : num -0.1 -1.4 -0.8 
$ Sepal.Length.4 : num 0.4 1 0.2 
$ Sepal.Length.5 : num 0.4 -0.8 1.1 
$ Sepal.Length.6 : num -0.8 0.6 -2.7 
$ Sepal.Length.7 : num 0.4 -1.4 2.4 
$ Sepal.Length.8 : num -0.6 1.7 -0.6 
$ Sepal.Length.9 : num 0.5 -1.4 0.5 
$ Sepal.Length.10: num 0.5 -0.2 -0.7