編集-この質問は、もともと<< 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
そして、私が最終的にしたいものは次のようになります。
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
などなど。不明な点は、長期データに追加情報が必要かどうか、または何が必要かです。数学の部分(平均と標準偏差を見つける)は簡単な部分になると思いますが、そのプロセスを開始するためにデータを正しく再形成するために機能するように見える方法を見つけることができませんでした。
助けてくれてありがとう。
これは、最初に質問が示唆したような再形成の問題ではなく、集約の問題です。IDごとに各列を平均と標準偏差に集約したいと考えています。そのような問題を処理する多くのパッケージがあります。 Rのベースでは、次のようにaggregate
を使用して実行できます(DF
が入力データフレームであると仮定):
_ag <- aggregate(. ~ ID, DF, function(x) c(mean = mean(x), sd = sd(x)))
_
注1:解説者は、ag
は一部の列が行列であるデータフレームであることを指摘しました。最初は奇妙に思えるかもしれませんが、実際にはアクセスが簡単になります。 ag
の列数は、入力DF
と同じです。最初の列_ag[[1]]
_はID
で、残りの_ag[[i+1]]
_(または同等に_ag[-1][[i]]
_)の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]]
を使用する必要があります。
たとえば、最初の式と2番目の式の単純さを比較します。
_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
_
注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)
_
おそらく最も簡単な方法です( 再現可能な例 ):
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
編集:次のアプローチは、多くの列を扱う際の入力を大幅に節約します。
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
それについてはいくつかの異なる方法があります。 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
また、これは役立つ場合と役に立たない場合があります
> 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
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
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