3

我从 3 个大型数据表(名为 A1、A2、A3)开始。每个表有 4 个数据列 (V1-V4)、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

您可以使用grepwithvalue = T来获取适当的名称,然后eval在 a 的j组件中创建调用data.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

我确信它可以做得更优雅,但这是一种似乎可行的可能性。

# 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.calland cbind(如 DWin 所建议的),我们连接各个列。Date最后,我们从原始数据框的列中设置列名。

该问题可以更优雅、更有效地解决,请参阅 DWin 和 Maiasaura 的解决方案。

于 2012-09-12T23:14:47.250 回答