我想使用几列来分割我的数据框,并在每个组上调用let {}} {/ p>}。
fivenum
返回的值是一个只有2列的data.frame,第二个是矩阵。如何将其转换为data.frame的普通列?
更新
我希望使用aggregate(Petal.Width ~ Species, iris, function(x) summary(fivenum(x)))
fivenum
答案 0 :(得分:10)
以下是使用data.table
的解决方案(虽然没有特别要求,但它是对aggregate
或ddply
的明显恭维或替代。除了代码稍长,反复调用quantile
效率低下,因为每次调用都会对数据进行排序
library(data.table)
Tukeys_five <- c("Min","Q1","Med","Q3","Max")
IRIS <- data.table(iris)
# this will create the wide data.table
lengthBySpecies <- IRIS[,as.list(fivenum(Sepal.Length)), by = Species]
# and you can rename the columns from V1, ..., V5 to something nicer
setnames(lengthBySpecies, paste0('V',1:5), Tukeys_five)
lengthBySpecies
Species Min Q1 Med Q3 Max
1: setosa 4.3 4.8 5.0 5.2 5.8
2: versicolor 4.9 5.6 5.9 6.3 7.0
3: virginica 4.9 6.2 6.5 6.9 7.9
或者,使用适当的quantile
参数对prob
进行一次调用。
IRIS[,as.list(quantile(Sepal.Length, prob = seq(0,1, by = 0.25))), by = Species]
Species 0% 25% 50% 75% 100%
1: setosa 4.3 4.800 5.0 5.2 5.8
2: versicolor 4.9 5.600 5.9 6.3 7.0
3: virginica 4.9 6.225 6.5 6.9 7.9
请注意,虽然您可以使用setnames
编辑
有趣的是,如果设置quantile
,names = TRUE
将设置生成的向量的名称,这将复制(减慢数字运算速度并消耗内存 - 它甚至在帮助中警告你,花哨该!)
因此,您应该使用
IRIS[,as.list(quantile(Sepal.Length, prob = seq(0,1, by = 0.25), names = FALSE)), by = Species]
或者,如果您想要返回命名列表,而不在内部复制{{1}
R
答案 1 :(得分:5)
您可以使用do.call
递归调用每个矩阵元素上的data.frame
来获取带有向量元素的data.frame:
dim(do.call("data.frame",dfr))
[1] 3 7
str(do.call("data.frame",dfr))
'data.frame': 3 obs. of 7 variables:
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 2 3
$ Petal.Width.Min. : num 0.1 1 1.4
$ Petal.Width.1st.Qu.: num 0.2 1.2 1.8
$ Petal.Width.Median : num 0.2 1.3 2
$ Petal.Width.Mean : num 0.28 1.36 2
$ Petal.Width.3rd.Qu.: num 0.3 1.5 2.3
$ Petal.Width.Max. : num 0.6 1.8 2.5
答案 2 :(得分:4)
据我所知,没有一种确切的方法来执行您所要求的操作,因为您正在使用的函数(fivenum)不会以一种可以轻松绑定到列的方式返回数据在'ddply'功能中。但是,这很容易以程序化的方式进行清理。
第1步:使用'ddply'函数对每个'Species'值执行fivenum
函数。
data <- ddply(iris, .(Species), summarize, value=fivenum(Petal.Width))
# Species value
# 1 setosa 0.1
# 2 setosa 0.2
# 3 setosa 0.2
# 4 setosa 0.3
# 5 setosa 0.6
# 6 versicolor 1.0
# 7 versicolor 1.2
# 8 versicolor 1.3
# 9 versicolor 1.5
# 10 versicolor 1.8
# 11 virginica 1.4
# 12 virginica 1.8
# 13 virginica 2.0
# 14 virginica 2.3
# 15 virginica 2.5
现在,'fivenum'函数返回一个列表,因此我们最终得到每个物种的5个行条目。这就是'fivenum'功能与我们作斗争的部分。
第2步:添加标签列。我们知道Tukey的五个数字是什么,所以我们只是按照'fivenum'函数返回它们的顺序调出它们。列表将重复,直到它到达数据的末尾。
Tukeys_five <- c("Min","Q1","Med","Q3","Max")
data$label <- Tukeys_five
# Species value label
# 1 setosa 0.1 Min
# 2 setosa 0.2 Q1
# 3 setosa 0.2 Med
# 4 setosa 0.3 Q3
# 5 setosa 0.6 Max
# 6 versicolor 1.0 Min
# 7 versicolor 1.2 Q1
# 8 versicolor 1.3 Med
# 9 versicolor 1.5 Q3
# 10 versicolor 1.8 Max
# 11 virginica 1.4 Min
# 12 virginica 1.8 Q1
# 13 virginica 2.0 Med
# 14 virginica 2.3 Q3
# 15 virginica 2.5 Max
第3步:使用标签,我们可以使用'reshape2'软件包中的'dcast'函数快速将此数据转换为新形状。
library(reshape2)
dcast(data, Species ~ label)[,c("Species",Tukeys_five)]
# Species Min Q1 Med Q3 Max
# 1 setosa 0.1 0.2 0.2 0.3 0.6
# 2 versicolor 1.0 1.2 1.3 1.5 1.8
# 3 virginica 1.4 1.8 2.0 2.3 2.5
最后的所有垃圾都只是指定列顺序,因为'dcast'函数会自动按字母顺序排列。
希望这有帮助。
更新:我决定回来,因为我意识到还有另外一个选项可供您使用。您始终可以将矩阵绑定为数据框定义的一部分,因此您可以像这样解析“聚合”函数:
data <- aggregate(Petal.Width ~ Species, iris, function(x) summary(fivenum(x)))
result <- data.frame(Species=data[,1],data[,2])
# Species Min. X1st.Qu. Median Mean X3rd.Qu. Max.
# 1 setosa 0.1 0.2 0.2 0.28 0.3 0.6
# 2 versicolor 1.0 1.2 1.3 1.36 1.5 1.8
# 3 virginica 1.4 1.8 2.0 2.00 2.3 2.5
答案 3 :(得分:0)
这是我的解决方案:
ddply(iris, .(Species), summarize, value=t(fivenum(Petal.Width)))