3

3 つの大きなデータ テーブル (A1、A2、A3 という名前) から始めています。各テーブルには、4 つのデータ列 (V1 ~ V4)、3 つのテーブルすべてで一定の 1 つの「日付」列、および数千の行があります。

これは、私のテーブルを近似するダミーデータです。

A1.V1<-c(1,2,3,4)
A1.V2<-c(2,4,6,8)
A1.V3<-c(1,3,5,7)
A1.V4<-c(1,2,3,4)


A2.V1<-c(1,2,3,4)
A2.V2<-c(2,4,6,8)
A2.V3<-c(1,3,5,7)
A2.V4<-c(1,2,3,4)


A3.V1<-c(1,2,3,4)
A3.V2<-c(2,4,6,8)
A3.V3<-c(1,3,5,7)
A3.V4<-c(1,2,3,4)

Date<-c(2001,2002,2003,2004)

DF<-data.frame(Date, A1.V1,A1.V2,A1.V3,A1.V4,A2.V1,A2.V2,A2.V3,A2.V4,A3.V1,A3.V2,A3.V3,A3.V4)

だから、これは私のデータフレームが最終的にどのように見えるかです:

  Date A1.V1 A1.V2 A1.V3 A1.V4 A2.V1 A2.V2 A2.V3 A2.V4 A3.V1 A3.V2 A3.V3 A3.V4
1 2001     1     2     1     1     1     2     1     1     1     2     1     1
2 2002     2     4     3     2     2     4     3     2     2     4     3     2
3 2003     3     6     5     3     3     6     5     3     3     6     5     3
4 2004     4     8     7     4     4     8     7     4     4     8     7     4

私の目標は、各データ テーブルから一致する各列の行平均を計算することです。したがって、この例では、V1 で終わるすべての列、V2 で終わるすべての列、V3 で終わるすべての列、および V4 で終わるすべての列の行平均が必要です。

最終結果は次のようになります

      V1  V2  V3  V4
2001   1   2   1   1
2002   2   4   3   2
2003   3   6   5   3
2004   4   8   7   4

だから私の質問は、列名の部分一致に基づいて行平均を計算するにはどうすればよいですか?

ありがとう

4

4 に答える 4

7
colnames = c("V1", "V2", "V3", "V4")
res <- sapply(colnames, function(x) rowMeans(DF [, grep(x, names(DF))] )  )
rownames(res) <- DF$Date
res
     V1 V2 V3 V4
2001  1  2  1  1
2002  2  4  3  2
2003  3  6  5  3
2004  4  8  7  4

Rgrep関数は、より大きなデータフレームから個々の「V」列名を含む列を選択的に「プル」するために使用される整数ベクトルを返します。

名前を自動的に生成する必要がある場合:

> unique(sapply(strsplit(names(DF)[-1], ".", fixed=TRUE), "[", 2) )
[1] "V1" "V2" "V3" "V4"
于 2012-09-12T23:48:14.553 に答える
4
library(plyr)
ddply(DF, .(Date), function(x) {
    foo <- melt(x, id.vars = 1)
    foo$variable <- substr(foo$variable, 4, 6)
    return(dcast(foo, Date ~ variable, mean))
    })
Date V1 V2 V3 V4
1 2001  1  2  1  1
2 2002  2  4  3  2
3 2003  3  6  5  3
4 2004  4  8  7  4
于 2012-09-12T23:25:32.373 に答える
2

grepwithを使用して適切な名前を取得し、コンポーネント内でvalue = T呼び出しを作成できますevaljdata.table

library(data.table)
# convert to a data.table
DT <- data.table(DF)
 # the indices we wish to group
.index <- paste0('V',1:3)
# a list containing the names
name_list <- mapply(grep, pattern = as.list(.index ), 
                  MoreArgs = list(x= names(DT),value=T ), SIMPLIFY=F)
 # create the expression
.e <- parse(text=sprintf('list( %s)', paste(mapply(sprintf, .index, lapply(name_list, paste, collapse = ', '), 
            MoreArgs = list(fmt = '%s = mean(c(%s), na.rm = T)')), collapse = ',')))

DT[, eval(.e),by=Date]

##    Date V1 V2 V3
## 1: 2001  1  2  1
## 2: 2002  2  4  3
## 3: 2003  3  6  5
## 4: 2004  4  8  7

# what .e looks like
.e 
## expression(list( V1 = mean(c(A1.V1, A2.V1, A3.V1), na.rm = T),V2 = mean(c(A1.V2, A2.V2, A3.V2), na.rm = T),V3 = mean(c(A1.V3, A2.V3, A3.V3), na.rm = T)))
于 2012-09-12T23:26:23.213 に答える
0

もっとエレガントにできると思いますが、これはうまくいくように見える可能性の1つです。

# declare the column names
colnames = c("V1", "V2", "V3", "V4")

# calculate the means
means = lapply(colnames, function(name) { apply(DF[,grep(name, names(DF))], 1, mean) })

# build the result
result = do.call(cbind, means)
result = as.data.frame(t(result))
rownames(result) = DF$Date

また、私がしたことを説明する必要があります。

まず、列名が部分的に一致することを宣言しました。

次に、grepコマンドを使用して、データフレーム内の(特定のサブストリングに一致する)列を部分的に選択します。このapplyコマンドは平均を計算lapplyし、部分文字列と部分的に一致するすべての列に対してそれを実行します。

do.callおよびcbind(DWinによって提案されているように)を使用して、個々の列を連結します。最後にDate、元のデータフレームの列から列名を設定します。

この問題は、より精巧かつ効率的に解決できます。DWinとMaiasauraによる解決策を参照してください。

于 2012-09-12T23:14:47.250 に答える