【问题标题】:generate a new variable that averages the rows of a group of columns in R生成一个新变量,平均 R 中一组列的行
【发布时间】:2012-08-07 00:49:55
【问题描述】:

我是 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

我想创建一个函数,可以按国家 obs 对列变量进行平均,如下所示:

       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

任何帮助将不胜感激。

【问题讨论】:

  • ?rowMeans。那是你要找的吗?此外,您的代码在大多数行的末尾都有额外的括号。
  • 请确保您的数值数据没有先保存为因子,否则在尝试应用答案时会出现错误并且没有结果!您的最后一个 data.frame 创建行可能应该是 df&lt;- data.frame(cname, gdp2003, gdp2004, corrupt2003, corrupt2004) 才能正常工作。

标签: arrays r


【解决方案1】:

首先您需要更改创建数据框的命令。通过使用 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

【讨论】:

  • 我知道 dataframe 命令已将它们更改为因子,但不是
  • 。 . .确定如何将它们改回数字。无论如何,这成功了。谢谢!
【解决方案2】:

虽然目前提供的解决方案肯定会奏效,但我建议以不同的方式构建您的数据。您在这里组合数据和字段名称:与其拥有一个名为“gdp2003”的字段,您实际上应该只拥有一个名为“gdp”的字段并拥有另一个名为“year”的字段,然后记录 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

【讨论】:

    【解决方案3】:

    您可以在选定的列上使用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])
    

    【讨论】:

    • rowMeans - M 不是 m - 仅此而已。 :-)
    猜你喜欢
    • 2014-04-30
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多