将基准年索引添加到具有多个组的R数据帧

时间:2015-07-30 09:18:17

标签: r dataframe

我有一个包含少量分组变量的年度时间序列数据框,我需要添加一个基于特定年份的索引列。

df <- data.frame(YEAR = c(2000,2001,2002,2000,2001,2002), 
                 GRP = c("A","A","A","B","B","B"),
                 VAL = sample(6))

我想创建一个简单的变量VAL索引,即值除以基准年的值,比如2000:

df$VAL.IND <- df$VAL/df$VAL[df$YEAR == 2000]

这是不对的,因为它不尊重分组变量GRP。我试过plyr,但我无法使它工作。

在我的实际问题中,我有几个具有不同时间序列的分组变量,因此我正在寻找一个非常通用的解决方案。

2 个答案:

答案 0 :(得分:3)

我们可以在分组变量('GRP')中进行计算后创建'VAL.IND'。这可以通过多种方式完成。

一个选项是data.table,我们从'data.frame'(setDT(df))创建'data.table',按'GRP'分组,我们将'VAL'除以'VAL'对应于2000年的'YEAR'值。

 library(data.table)
 setDT(df)[, VAL.IND := VAL/VAL[YEAR==2000], by = GRP]

注意:base年对结果有点混乱。在示例中,'A'和'B'GRP都有'YEAR'2000。假设,如果OP意味着使用最小YEAR值(考虑到它是数字列),上面代码中的VAL/VAL[YEAR==2000]可以替换为VAL/VAL[which.min(YEAR)]

或者您可以使用与dplyr类似的代码。我们按'GRP'分组并使用mutate创建'VAL.IND'

 library(dplyr)
 df %>%
    group_by(GRP) %>%
    mutate(VAL.IND = VAL/VAL[YEAR==2000])

此处,如果我们需要将VAL/VAL[YEAR==2000]替换为VAL/VAL[which.min(YEAR)]

base R选项split/unsplit。我们通过“GRP”列split数据集将data.frame转换为list个数据帧,使用list循环遍历lapply输出,创建一个使用transform(或within)的新列,并将添加了列的list转换为data.frame的单个unsplit

  unsplit(lapply(split(df, df$GRP), function(x) 
          transform(x, VAL.IND= VAL/VAL[YEAR==2000])), df$GRP)

请注意,我们也可以使用do.call(rbind代替unsplit。但是,我更喜欢unsplit获得与原始数据集相同的行顺序。

答案 1 :(得分:2)

这是围绕by()建立的另一种基础R方法:

df$VAL.IND <- do.call(c,by(df,df$GRP,function(g) g$VAL/g$VAL[which.min(g$YEAR)]));
df;
##   YEAR GRP VAL   VAL.IND
## 1 2000   A   3 1.0000000
## 2 2001   A   1 0.3333333
## 3 2002   A   2 0.6666667
## 4 2000   B   6 1.0000000
## 5 2001   B   5 0.8333333
## 6 2002   B   4 0.6666667