我是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
的结果管理此问题感到非常好奇,但我可以使用在plyr
或reshape
中完成所有操作的解决方案。
答案 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