use*_*358 25 aggregate r reshape reshape2
编辑 - 这个问题最初的标题是"R中的长到宽数据重塑"
我只是在学习R并试图找到方法来应用它来帮助我生命中的其他人.作为一个测试用例,我正在努力重塑一些数据,而且我在跟踪我在网上发现的例子时遇到了麻烦.我开始的是这样的:
ID Obs 1 Obs 2 Obs 3
1 43 48 37
1 27 29 22
1 36 32 40
2 33 38 36
2 29 32 27
2 32 31 35
2 25 28 24
3 45 47 42
3 38 40 36
Run Code Online (Sandbox Code Playgroud)
而我想要最终得到的将是这样的:
ID Obs 1 mean Obs 1 std dev Obs 2 mean Obs 2 std dev
1 x x x x
2 x x x x
3 x x x x
Run Code Online (Sandbox Code Playgroud)
等等.我不确定的是我是否需要在长篇数据中提供更多信息,或者是什么.我想,数学部分(找到平均值和标准偏差)将是容易的部分,但我找不到一种似乎能够正确地重塑数据以开始该过程的方法.
非常感谢您的帮助.
G. *_*eck 31
这是一个聚合问题,而不是最初建议的问题的重塑问题 - 我们希望通过ID将每列合并为均值和标准差.有许多包处理这些问题.在R的基础上,可以aggregate像这样使用(假设DF是输入数据帧):
ag <- aggregate(. ~ ID, DF, function(x) c(mean = mean(x), sd = sd(x)))
Run Code Online (Sandbox Code Playgroud)
注1:评论者指出,这ag是一些数据框,其中某些列是矩阵.虽然最初可能看起来很奇怪,但事实上它简化了访问. ag具有与输入相同的列数DF.它的第一列ag[[1]]是ID,其余的第i列ag[[i+1]](或等效ag[-1][[i]])是第i个输入观察列的统计矩阵.如果希望访问第i个观察的第j个统计量,那么它ag[[i+1]][, j]也可以被写为ag[-1][[i]][, j].
另一方面,假设k输入中的每个观察都有统计列(问题中k = 2).然后,如果我们展平输出然后访问第i个观察列的第j个统计量,我们必须使用更复杂ag[[k*(i-1)+j+1]]或等效的ag[-1][[k*(i-1)+j]].
例如,比较第一个表达式与第二个表达式的简单性:
ag[-1][[2]]
## mean sd
## [1,] 36.333 10.2144
## [2,] 32.250 4.1932
## [3,] 43.500 4.9497
ag_flat <- do.call("data.frame", ag) # flatten
ag_flat[-1][, 2 * (2-1) + 1:2]
## Obs_2.mean Obs_2.sd
## 1 36.333 10.2144
## 2 32.250 4.1932
## 3 43.500 4.9497
Run Code Online (Sandbox Code Playgroud)
注2:可重复形式的输入是:
Lines <- "ID Obs_1 Obs_2 Obs_3
1 43 48 37
1 27 29 22
1 36 32 40
2 33 38 36
2 29 32 27
2 32 31 35
2 25 28 24
3 45 47 42
3 38 40 36"
DF <- read.table(text = Lines, header = TRUE)
Run Code Online (Sandbox Code Playgroud)
Car*_*son 18
这可能是最简单的方法(使用可重复的示例):
library(plyr)
df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
ddply(df, .(ID), summarize, Obs_1_mean=mean(Obs_1), Obs_1_std_dev=sd(Obs_1),
Obs_2_mean=mean(Obs_2), Obs_2_std_dev=sd(Obs_2))
ID Obs_1_mean Obs_1_std_dev Obs_2_mean Obs_2_std_dev
1 1 -0.13994642 0.8258445 -0.15186380 0.4251405
2 2 1.49982393 0.2282299 0.50816036 0.5812907
3 3 -0.09269806 0.6115075 -0.01943867 1.3348792
Run Code Online (Sandbox Code Playgroud)
编辑:以下方法在处理许多列时为您节省了大量的输入.
ddply(df, .(ID), colwise(mean))
ID Obs_1 Obs_2 Obs_3
1 1 -0.3748831 0.1787371 1.0749142
2 2 -1.0363973 0.0157575 -0.8826969
3 3 1.0721708 -1.1339571 -0.5983944
ddply(df, .(ID), colwise(sd))
ID Obs_1 Obs_2 Obs_3
1 1 0.8732498 0.4853133 0.5945867
2 2 0.2978193 1.0451626 0.5235572
3 3 0.4796820 0.7563216 1.4404602
Run Code Online (Sandbox Code Playgroud)
Ric*_*rta 16
有几种不同的方法可以解决它. reshape2是一个有用的包.就个人而言,我喜欢使用data.table
以下是一步一步的说明
如果myDF是你的data.frame:
library(data.table)
DT <- data.table(myDF)
DT
# this will get you your mean and SD's for each column
DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x)))]
# adding a `by` argument will give you the groupings
DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x))), by=ID]
# If you would like to round the values:
DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID]
# If we want to add names to the columns
wide <- setnames(DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID], c("ID", sapply(names(DT)[-1], paste0, c(".men", ".SD"))))
wide
ID Obs.1.men Obs.1.SD Obs.2.men Obs.2.SD Obs.3.men Obs.3.SD
1: 1 35.333 8.021 36.333 10.214 33.0 9.644
2: 2 29.750 3.594 32.250 4.193 30.5 5.916
3: 3 41.500 4.950 43.500 4.950 39.0 4.243
Run Code Online (Sandbox Code Playgroud)
此外,这可能有用也可能没用
> DT[, sapply(.SD, summary), .SDcols=names(DT)[-1]]
Obs.1 Obs.2 Obs.3
Min. 25.00 28.00 22.00
1st Qu. 29.00 31.00 27.00
Median 33.00 32.00 36.00
Mean 34.22 36.11 33.22
3rd Qu. 38.00 40.00 37.00
Max. 45.00 48.00 42.00
Run Code Online (Sandbox Code Playgroud)
我添加了dplyr解决方案.
set.seed(1)
df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
library(dplyr)
df %>% group_by(ID) %>% summarise_each(funs(mean, sd))
# ID Obs_1_mean Obs_2_mean Obs_3_mean Obs_1_sd Obs_2_sd Obs_3_sd
# (int) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl)
# 1 1 0.4854187 -0.3238542 0.7410611 1.1108687 0.2885969 0.1067961
# 2 2 0.4171586 -0.2397030 0.2041125 0.2875411 1.8732682 0.3438338
# 3 3 -0.3601052 0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692
Run Code Online (Sandbox Code Playgroud)
这是对data.table答案的另一种看法,使用@ Carson的数据,它更具可读性(而且速度更快,因为使用lapply而不是sapply):
library(data.table)
set.seed(1)
dt = data.table(ID=c(1:3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9))
dt[, c(mean = lapply(.SD, mean), sd = lapply(.SD, sd)), by = ID]
# ID mean.Obs_1 mean.Obs_2 mean.Obs_3 sd.Obs_1 sd.Obs_2 sd.Obs_3
#1: 1 0.4854187 -0.3238542 0.7410611 1.1108687 0.2885969 0.1067961
#2: 2 0.4171586 -0.2397030 0.2041125 0.2875411 1.8732682 0.3438338
#3: 3 -0.3601052 0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692
Run Code Online (Sandbox Code Playgroud)