生成一个新变量,用于平均R中一组列的行

时间:2012-08-07 00:49:55

标签: arrays r

我是R.的新手。我正在使用一个比较面板数据集,其中一个关键变量是时间的横截面,因此我必须在该时间段内平均所有变量。

数据的格式如下:行是国家观察,列是变量年。

我构建了这个例子:

cname<- c("ARGENTINA", "BOLIVIA", "CHILE", "CHINA", "ECUADOR", "EGYPT")
gdp2003<- c(1.5, 2.3, 5.2, 12, 2.3, 3.3)
gdp2004<- c(1.7, 2.2, 4.7, 13.3, 1.7, 1.5)
corrupt2003<- c(5.1, 6.7, 3.4, 5.5, 4.5, 8.7)
corrupt2004<- c(4.5, 5.4, 2.4, 4.5, 5.4, 8.9)
df<- data.frame(cbind(cname, gdp2003, gdp2004, corrupt2003, corrupt2004))
df

生成此输出:

     cname gdp2003 gdp2004 corrupt2003 corrupt2004
1 ARGENTINA     1.5     1.7         5.1         4.5
2   BOLIVIA     2.3     2.2         6.7         5.4
3     CHILE     5.2     4.7         3.4         2.4
4     CHINA      12    13.3         5.5         4.5
5   ECUADOR     2.3     1.7         4.5         5.4
6     EGYPT     3.3     1.5         8.7         8.9

我想创建一个可以按国家/地区平均列变量的函数,如下所示:

       cname gdp2003 gdp2004 corrupt2003 corrupt2004 new.col.gdp new.col.corrupt
1 ARGENTINA     1.5     1.7         5.1         4.5         1.6             4.8
2   BOLIVIA     2.3     2.2         6.7         5.4        2.25            6.05
3     CHILE     5.2     4.7         3.4         2.4        4.95             2.9
4     CHINA      12    13.3         5.5         4.5       12.65               5
5   ECUADOR     2.3     1.7         4.5         5.4           2            4.95
6     EGYPT     3.3     1.5         8.7         8.9         2.4             8.8

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

首先,您需要更改创建数据框的命令。通过使用cbind(),您将所有数字列转换为文本(以匹配作为文本的cname列。然后,当您创建data.frame时,R将这些文本列转换为因子。还要将data.frame名称更改为DF避免与函数df()的任何冲突:

DF<- data.frame(cname, gdp2003, gdp2004, corrupt2003, corrupt2004)
vars <-c("gdp","corrupt")
new.cols <- sapply(vars, function(i) rowMeans(DF[, grepl(i, colnames(DF))]))
colnames(new.cols) <- paste0(colnames(new.cols), ".mean")
DF <- data.frame(DF, new.cols)
DF

答案 1 :(得分:2)

您可以在选择列上使用rowMeans

df$new.col.gdp <- rowMeans(df[,2:3])
df$new.col.corrupt <- rowMeans(df[,3:4])

现在,让我们说你并不真正知道你想要的所有列数,但你碰巧知道它们都会包含名称中常见的东西。让我们说它是'gdp'。你可以使用类似的东西。

selectColumns <- grep('gdp', names(df))
df$new.col.gdp <- rowMeans(df[,selectColumns])

答案 2 :(得分:2)

虽然到目前为止提供的解决方案肯定会有用,但我建议以不同的方式构建数据。你在这里组合数据和字段名称:而不是有一个名为&#34; gdp2003&#34;的字段,你应该只有一个名为&#34; gdp&#34;的字段。还有一个名为&#34; year&#34;然后有一个gdp的记录是2003年的年份。关于这种方法的更多信息,我强烈建议阅读Hadley Wickham的论文Tidy Data

以下是如何修改以这种方式设置数据的方法:

df <- data.frame(country=cname, year=2003, gdp=gdp2003,
                 corrupt=corrupt2003)
df <- rbind(df, data.frame(country=cname, year=2004,
                 gdp=gdp2004, corrupt=corrupt2004))

您的数据框现在应如下所示:

     country year  gdp corrupt
1  ARGENTINA 2003  1.5     5.1
2    BOLIVIA 2003  2.3     6.7
3      CHILE 2003  5.2     3.4
4      CHINA 2003 12.0     5.5
5    ECUADOR 2003  2.3     4.5
6      EGYPT 2003  3.3     8.7
7  ARGENTINA 2004  1.7     4.5
8    BOLIVIA 2004  2.2     5.4
9      CHILE 2004  4.7     2.4
10     CHINA 2004 13.3     4.5
11   ECUADOR 2004  1.7     5.4
12     EGYPT 2004  1.5     8.9

在这种形式下,您会发现以后添加数据更容易,并且仍然使用您的代码来计算平均值。一种方法是使用by

by(df[,-(1:2)], df$country, colMeans)

将为您提供平均值列表:

df$country: ARGENTINA
    gdp corrupt 
    1.6     4.8 
------------------------------------------------------------ 
df$country: BOLIVIA
    gdp corrupt 
   2.25    6.05 

[etc]

你可以把它变成一个更好的表格,如下所示:

t(simplify2array(by(df[,-(1:2)], df$country, colMeans)))

            gdp corrupt
ARGENTINA  1.60    4.80
BOLIVIA    2.25    6.05
CHILE      4.95    2.90
CHINA     12.65    5.00
ECUADOR    2.00    4.95
EGYPT      2.40    8.80

使用整洁的数据时,为了获得更大的灵活性,请查看plyr包。

ddply(df, .(country), summarise, gdp=mean(gdp), corrupt=mean(corrupt))

如果您需要平均值和原始结果(例如,如果您想计算每年平均值的差异):

ddply(df, .(country), transform, gdp.m=mean(gdp), corrupt.m=mean(corrupt))

      country year  gdp corrupt gdp.m corrupt.m
1  ARGENTINA 2003  1.5     5.1  1.60      4.80
2  ARGENTINA 2004  1.7     4.5  1.60      4.80
3    BOLIVIA 2003  2.3     6.7  2.25      6.05
4    BOLIVIA 2004  2.2     5.4  2.25      6.05
5      CHILE 2003  5.2     3.4  4.95      2.90
6      CHILE 2004  4.7     2.4  4.95      2.90
7      CHINA 2003 12.0     5.5 12.65      5.00
8      CHINA 2004 13.3     4.5 12.65      5.00
9    ECUADOR 2003  2.3     4.5  2.00      4.95
10   ECUADOR 2004  1.7     5.4  2.00      4.95
11     EGYPT 2003  3.3     8.7  2.40      8.80
12     EGYPT 2004  1.5     8.9  2.40      8.80