17

applyまたは関連する関数を使用して、非常に大きなデータ フレーム内の列の各ペアの行平均の結果を含む新しいデータ フレームを作成するにはどうすればよいですか?

n私は、多数のサンプルの反復測定値を出力する機器を持っています。ここで、各測定値はベクトルです (すべての測定値は同じ長さのベクトルです)。各サンプルのすべての反復測定値の平均 (およびその他の統計) を計算したいと思います。これは、n連続する列をグループ化し、行ごとの計算を行う必要があることを意味します。

簡単な例として、2 つのサンプルで 3 回の反復測定を行うとdat$a、どのようにして 2 つの列 (サンプルごとに 1 つ) を持つデータ フレームになるのでしょうか。、およびの各行の平均。dat$bdat$cdat$ddat$edat$f

ここにいくつかのサンプルデータがあります

dat <- data.frame( a = rnorm(16), b = rnorm(16), c = rnorm(16), d = rnorm(16), e = rnorm(16), f = rnorm(16))

            a          b            c          d           e          f
1  -0.9089594 -0.8144765  0.872691548  0.4051094 -0.09705234 -1.5100709
2   0.7993102  0.3243804  0.394560355  0.6646588  0.91033497  2.2504104
3   0.2963102 -0.2911078 -0.243723116  1.0661698 -0.89747522 -0.8455833
4  -0.4311512 -0.5997466 -0.545381175  0.3495578  0.38359390  0.4999425
5  -0.4955802  1.8949285 -0.266580411  1.2773987 -0.79373386 -1.8664651
6   1.0957793 -0.3326867 -1.116623982 -0.8584253  0.83704172  1.8368212
7  -0.2529444  0.5792413 -0.001950741  0.2661068  1.17515099  0.4875377
8   1.2560402  0.1354533  1.440160168 -2.1295397  2.05025701  1.0377283
9   0.8123061  0.4453768  1.598246016  0.7146553 -1.09476532  0.0600665
10  0.1084029 -0.4934862 -0.584671816 -0.8096653  1.54466019 -1.8117459
11 -0.8152812  0.9494620  0.100909570  1.5944528  1.56724269  0.6839954
12  0.3130357  2.6245864  1.750448404 -0.7494403  1.06055267  1.0358267
13  1.1976817 -1.2110708  0.719397607 -0.2690107  0.83364274 -0.6895936
14 -2.1860098 -0.8488031 -0.302743475 -0.7348443  0.34302096 -0.8024803
15  0.2361756  0.6773727  1.279737692  0.8742478 -0.03064782 -0.4874172
16 -1.5634527 -0.8276335  0.753090683  2.0394865  0.79006103  0.5704210

私はこのようなものを求めています

            X1          X2
1  -0.28358147 -0.40067128
2   0.50608365  1.27513471
3  -0.07950691 -0.22562957
4  -0.52542633  0.41103139
5   0.37758930 -0.46093340
6  -0.11784382  0.60514586
7   0.10811540  0.64293184
8   0.94388455  0.31948189
9   0.95197629 -0.10668118
10 -0.32325169 -0.35891702
11  0.07836345  1.28189698
12  1.56269017  0.44897971
13  0.23533617 -0.04165384
14 -1.11251880 -0.39810121
15  0.73109533  0.11872758
16 -0.54599850  1.13332286

私はこれでこれを行いましたが、明らかに私のはるかに大きなデータフレームには適していません...

data.frame(cbind(
apply(cbind(dat$a, dat$b, dat$c), 1, mean),
apply(cbind(dat$d, dat$e, dat$f), 1, mean)
))

私は試しapplyてループしましたが、うまくまとめることができません。私の実際のデータには数百の列があります。

4

6 に答える 6

18

これは、インデックスのリストを渡すという点で、状況により一般化できる場合があります。速度が問題になる場合(大きなデータフレーム)、私は次の代わりに選択lapplyします:do.callsapply

x <- list(1:3, 4:6)
do.call(cbind, lapply(x, function(i) rowMeans(dat[, i])))

col名だけでも機能します:

x <- list(c('a','b','c'), c('d', 'e', 'f'))
do.call(cbind, lapply(x, function(i) rowMeans(dat[, i])))

編集

たまたま、これを自動化して3列ごとに実行したいと思ったのかもしれません。より良い方法があることは知っていますが、ここでは100列のデータセットにあります。

dat <- data.frame(matrix(rnorm(16*100), ncol=100))

n <- 1:ncol(dat)
ind <- matrix(c(n, rep(NA, 3 - ncol(dat)%%3)), byrow=TRUE, ncol=3)
ind <- data.frame(t(na.omit(ind)))
do.call(cbind, lapply(ind, function(i) rowMeans(dat[, i])))

編集2 まだ索引付けに満足していません。インデックスを渡すためのより良い/より速い方法があると思います。これは、満足のいく方法ではありませんが、2番目の方法です。

n <- 1:ncol(dat)
ind <- data.frame(matrix(c(n, rep(NA, 3 - ncol(dat)%%3)), byrow=F, nrow=3))
nonna <- sapply(ind, function(x) all(!is.na(x)))
ind <- ind[, nonna]

do.call(cbind, lapply(ind, function(i)rowMeans(dat[, i])))
于 2012-05-19T01:03:13.133 に答える
8

同様の質問が @david によってここで尋ねられました: r の 16 列ごとの平均化(現在はクローズされています)。これには、@joran と @Ben の提案に従って、上記の @TylerRinker の回答を適応させることで回答しました。結果の関数は OP または将来の読者に役立つ可能性があるため、OP のデータの例とともに、その関数をここにコピーします。

# Function to apply 'fun' to object 'x' over every 'by' columns
# Alternatively, 'by' may be a vector of groups
byapply <- function(x, by, fun, ...)
{
    # Create index list
    if (length(by) == 1)
    {
        nc <- ncol(x)
        split.index <- rep(1:ceiling(nc / by), each = by, length.out = nc)
    } else # 'by' is a vector of groups
    {
        nc <- length(by)
        split.index <- by
    }
    index.list <- split(seq(from = 1, to = nc), split.index)

    # Pass index list to fun using sapply() and return object
    sapply(index.list, function(i)
            {
                do.call(fun, list(x[, i], ...))
            })
}

次に、複製の平均を見つけるには、次のようにします。

byapply(dat, 3, rowMeans)

または、おそらくレプリケートの標準偏差:

byapply(dat, 3, apply, 1, sd)

アップデート

byグループのベクトルとして指定することもできます。

byapply(dat, c(1,1,1,2,2,2), rowMeans)
于 2012-05-22T17:51:50.783 に答える
7

ベクトル a,b,c からの行の平均

 rowMeans(dat[1:3])

ベクトル d,e,f からの行の平均

 rowMeans(dat[4:6])

1回の通話ですべて取得

results<-cbind(rowMeans(dat[1:3]),rowMeans(dat[4:6]))

列の名前だけがわかり、順序がわからない場合は、次を使用できます。

rowMeans(cbind(dat["a"],dat["b"],dat["c"]))
rowMeans(cbind(dat["d"],dat["e"],dat["f"]))

#I dont know how much damage this does to speed but should still be quick
于 2012-05-19T00:30:36.850 に答える
5

rowMeansソリューションはより高速になりますが、完全を期すために、これを行う方法は次のとおりapplyです。

t(apply(dat,1,function(x){ c(mean(x[1:3]),mean(x[4:6])) }))
于 2012-05-19T00:34:50.073 に答える
2

@joranの提案に触発されて、私はこれを思いつきました(実際には、彼が提案したものとは少し異なりますが、転置の提案は特に役立ちました):

cols を使用してサンプル データのデータ フレームを作成しp、現実的なデータ セットをシミュレートします (上記の @TylerRinker の回答に従い、質問の私の貧弱な例とは異なります)。

p <- 99 # how many columns?
dat <- data.frame(matrix(rnorm(4*p), ncol = p))

このデータ フレームの列の名前を変更して、n連続した列のグループを作成します。3 つの列のグループに関心がある場合は、1,1,1,2,2,2,3,3,3 のような列名が得られます。など、または 4 つの列のグループが必要な場合は、1、1、1、1、2、2、2、2、3、3、3、3 などになります。今のところ 3 つを使用します (これだと思います)。インデックス作成についてあまり知らない私のような人のための一種のインデックス作成です)

n <- 3 # how many consecutive columns in the groups of interest?
names(dat) <- rep(seq(1:(ncol(dat)/n)), each = n, len = (ncol(dat)))

apply と tapply を使用して、各グループの行平均を取得します。

dat.avs <- data.frame(t(apply(dat, 1, tapply, names(dat), mean)))

主な欠点は、元のデータの列名が置き換えられること (ただし、これは列名ではなく新しい行にグループ化番号を配置することで克服できます) と、apply-tapply 関数によって列名が役に立たない形式で返されることです。注文。

@joranの提案に加えて、data.table解決策は次のとおりです。

p <- 99 # how many columns?
dat <- data.frame(matrix(rnorm(4*p), ncol = p))
dat.t <-  data.frame(t(dat))

n <- 3 # how many consecutive columns in the groups of interest?
dat.t$groups <- as.character(rep(seq(1:(ncol(dat)/n)), each = n, len = (ncol(dat))))

library(data.table)
DT <- data.table(dat.t)
setkey(DT, groups)
dat.av <- DT[, lapply(.SD,mean), by=groups]

皆さんの迅速かつ忍耐強い努力に感謝します!

于 2012-05-19T04:10:41.403 に答える
0

コンビナトリクスとして知られている、列の一意の組み合わせごとに関数を適用することに興味がある場合は、美しくシンプルなソリューションがあります。

combinations <- combn(colnames(df),2,function(x) rowMeans(df[x]))

apply3 つの列などの一意の組み合わせごとに統計を計算するには、2 を 3 に変更するだけです。演算はベクトル化されるため、上記で使用したファミリ関数などのループよりも高速です。列の順序が重要な場合は、代わりに、順序付けられたセットを再現するように設計された順列アルゴリズムが必要です。combinat::permn

于 2015-10-05T17:39:04.497 に答える