展平/非规范化R聚合函数的结果

时间:2013-03-01 22:42:54

标签: r aggregate plyr reshape

我是R的新手,我正在尝试使用aggregate对数据框,每个主题以及我的数据集中的每个指标执行一些时间序列整形。这很好用,但我发现结果不是一种非常容易使用的格式。我希望能够将结果转换回与原始数据帧相同的格式。

以虹膜数据集为例:

# 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中完成所有操作的解决方案。

4 个答案:

答案 0 :(得分: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),因为这样做了你想要的矩阵(但不是数据帧)。关键点在于函数返回的行数与Species中每个iris的行数不同。

答案 1 :(得分:2)

在这种情况下,我能想到的最佳解决方案是data.table

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

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

require(plyr)
ddply(iris, .(Species), function(x) do.call(cbind, lapply(x[,1:4], diff)))

答案 2 :(得分:1)

如果你想返回某种与输入向量长度相同的第一个差异向量,你应该使用ave和anonymous函数。由于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 ...

答案 3 :(得分:1)

以下是我理解为您的问题:使用您当前使用aggregate的方法,您会得到{Sepner.Length“,”Sepal.Width“的结果matrix,依此类推

> 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。以下是您使用现有输出的方法(我从@James获取的一个技巧,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