我有一个数据框,其中一列是矩阵,而不是矢量,我想将其拆分为多个矢量值列。
例如,这个
set.seed(101)
Df <- data.frame(x = runif(100),
y = round(runif(100)))
descriptives <- function(arg) c(mean(arg), median(arg), sd(arg))
results <- aggregate(x ~ y, data=Df, descriptives)
给了我
> results
y x.1 x.2 x.3
1 0 0.4710224 0.4280053 0.3206661
2 1 0.5769064 0.6220120 0.2683387
是2x2数据帧,第二列是2x3矩阵:
> dim(results)
[1] 2 2
> results[,2]
[,1] [,2] [,3]
[1,] 0.4710224 0.4280053 0.3206661
[2,] 0.5769064 0.6220120 0.2683387
我想将该矩阵分成三个列向量。
我能做到
results <- cbind(results$y, as.data.frame(results[,2]))
names(results) <- c('y', 'mean', 'median', 'sd')
> results
y mean median sd
1 0 0.4710224 0.4280053 0.3206661
2 1 0.5769064 0.6220120 0.2683387
但是有更直接和更少的hacky方式吗?我在想tidyr
的{{1}}之类的东西?
答案 0 :(得分:1)
在这种情况下,使用矩阵,您可以使用cbind
:
cbind(results[1], results[[2]])
# y 1 2 3
# 1 0 0.4710224 0.4280053 0.3206661
# 2 1 0.5769064 0.6220120 0.2683387
在第一个参数上使用[
确保它是data.frame
,因此使用cbind.data.frame
并且结果不会强制转换为矩阵。但是在第二个参数上使用[[
可以确保我们绑定到第二列中的2x3
矩阵,而不是包含该矩阵的数据框。
更一般地说,tidyr::unnest
适用于vector
或list
列,但结果是长格式的 - 您必须添加列ID并将其展开以将其恢复广泛的形式。
但是,最简单的方法可能是将dplyr
和summarize_at
与自定义.funs
参数一起使用:
library(dplyr)
descrip = funs(m = mean, med = median, sd = sd)
Df %>% group_by(y) %>% summarize_at("x", .funs = descrip)
# # A tibble: 2 × 4
# y m med sd
# <dbl> <dbl> <dbl> <dbl>
# 1 0 0.4710224 0.4280053 0.3206661
# 2 1 0.5769064 0.6220120 0.2683387
答案 1 :(得分:1)
是。使用dplyr
相对容易。
library(dplyr)
results <- Df %>% group_by(y) %>%
summarize(mean = mean(x),
median = median(x),
sd = sd(x))
答案 2 :(得分:1)
一个基本R替代方案是使用aggregate
,tapply
的内部函数,并使用lapply
来运行每个统计计算:
# collect desired statistical calculations in a named list
descriptives <- list(mean=mean, median=median, sd=sd)
# get data.frame of values
dfStats <- data.frame(lapply(descriptives, function(f) tapply(Df$x, Df$y, f)))
dfStats
mean median sd
0 0.4710224 0.4280053 0.3206661
1 0.5769064 0.6220120 0.2683387
此处,lapply
遍历函数列表并应用tapply
来获取组计算。生成的列表将放入带有data.frame
的data.frame中。请注意,y是此处的row.names,但您可以轻松地将其拉出row.names
。
dfStats$y <- row.names(dfStats)
答案 3 :(得分:1)
修复问题的一种方法(但正如其他人指出的那样,问题可能是避免)是使用do.call(data.frame, ...)
。
示例:
do.call(data.frame, results)
# y x.1 x.2 x.3
# 1 0 0.4710224 0.4280053 0.3206661
# 2 1 0.5769064 0.6220120 0.2683387
str(.Last.value)
# 'data.frame': 2 obs. of 4 variables:
# $ y : num 0 1
# $ x.1: num 0.471 0.577
# $ x.2: num 0.428 0.622
# $ x.3: num 0.321 0.268