基于多个数据子集条件的行值创建新列

时间:2017-11-17 14:38:13

标签: r dataframe

我的数据框看起来或多或少如下(原始数据框有12年的数据):

   Year   Quarter   Age_1   Age_2   Age_3   Age_4
   2005      1       158     120     665     32
   2005      2       257     145     121     14
   2005      3       68       69     336     65
   2005      4       112     458     370     101
   2006      1       75      457     741     26
   2006      2       365     134     223     45
   2006      3       257     121     654     341
   2006      4       175     124     454     12
   2007      1       697     554     217     47
   2007      2       954     987     118     54
   2007      4       498     235     112     65

年龄栏中的数字表示特定年份内特定季度的每个年龄组的个人数量。值得注意的是,有时并非特定年份的所有季度都有数据(例如,第三季度没有代表2007年)。此外,每行代表一个采样事件。虽然在此示例中未显示,但在原始数据集中,对于特定年份内的特定季度,我总是有多个采样事件。例如,对于2005年的第一季度,我有47个抽样事件,因此导致47行。

我现在想要的是一个数据框,结构如下:

       Year   Quarter   Age_1   Age_2   Age_3   Age_4    Cohort
       2005      1       158     120     665     32        158
       2005      2       257     145     121     14        257
       2005      3       68       69     336     65         68
       2005      4       112     458     370     101       112
       2006      1       75      457     741     26        457 
       2006      2       365     134     223     45        134
       2006      3       257     121     654     341       121
       2006      4       175     124     454     12        124
       2007      1       697     554     217     47         47
       2007      2       954     987     118     54         54
       2007      4       498     235     112     65         65

在这种情况下,我想在我的原始数据集中创建一个新列(同类群组),它基本上沿着我的数据集跟踪我的同类群组。换句话说,当我在我的第一年数据(2005年的所有季度)中,我获取Age_1的行值并将其粘贴到新列中。当我移动到下一年(2006年)时,我将所有与Age_2相关的行值并将其粘贴到新列,依此类推。

我曾尝试使用以下功能,但不知何故它只适用于前几年:

extract_cohort_quarter <- function(d, yearclass=2005, quarterclass=1) {

 ny <- 1:nlevels(d$Year) #no. of Year levels in the dataset 
 nq <- 1:nlevels(d$Quarter)
 age0 <- (paste("age", ny, sep="_"))
 year0 <- as.character(yearclass + ny - 1)

quarter <- as.character(rep(1:4, length(age0)))
age <- rep(age0,each=4)
year <- rep(year0,each=4)

df <- data.frame(year,age,quarter,stringsAsFactors=FALSE)

n <- nrow(df)
dnew <- NULL
for(i in 1:n) {
    tmp <- subset(d, Year==df$year[i] & Quarter==df$quarter[i])
    tmp$Cohort <- tmp[[age[i]]]
    dnew <- rbind(dnew, tmp)
}
levels(dnew$Year) <- paste("Yearclass_", yearclass, ":", 
year,":",quarter,":", age, sep="")
dnew
}

我的所有年份和季度都有大量从age_1到age_12的数据,因此我认为这与数据结构本身无关。

有没有更简单的解决方案来解决这个问题?或者有没有办法改进我的extract_cohort_quarter()函数?任何帮助将不胜感激。

-M

2 个答案:

答案 0 :(得分:2)

我有一个简单的解决方案,但需要对data.table库有点了解。我认为您可以轻松地根据您的进一步需求进行调整。 这是数据:

DT <- as.data.table(list(Year   = c(2005,   2005,   2005,   2005,   2006,   2006    ,2006   ,2006,  2007,   2007,   2007),
                         Quarter= c(1,  2,  3,  4   ,1  ,2  ,3  ,4  ,1  ,2  ,4),
                         Age_1  = c(158,    257,    68, 112 ,75,    365,    257,    175,    697 ,954,   498),
                         Age_2= c(120   ,145    ,69 ,458    ,457,   134 ,121    ,124    ,554    ,987,   235),
                         Age_3= c(665   ,121    ,336    ,370    ,741    ,223    ,654    ,454,217,118,112),
                         Age_4= c(32,14,65,101,26,45,341,12,47,54,65)

))

这是代码:

DT[,index := .GRP, by = Year]
DT[,cohort := get(paste0("Age_",index)),by = Year]

和输出:

> DT
    Year Quarter Age_1 Age_2 Age_3 Age_4 index cohort
 1: 2005       1   158   120   665    32     1    158
 2: 2005       2   257   145   121    14     1    257
 3: 2005       3    68    69   336    65     1     68
 4: 2005       4   112   458   370   101     1    112
 5: 2006       1    75   457   741    26     2    457
 6: 2006       2   365   134   223    45     2    134
 7: 2006       3   257   121   654   341     2    121
 8: 2006       4   175   124   454    12     2    124
 9: 2007       1   697   554   217    47     3    217
10: 2007       2   954   987   118    54     3    118
11: 2007       4   498   235   112    65     3    112

它的作用:

DT[,index := .GRP, by = Year]

为表中的所有不同年份创建索引(by = Year为年度组创建操作,.GRP在分组序列后创建索引)。 我使用它来调用名为Age_的列,并使用创建的数字

DT[,cohort := get(paste0("Age_",index)),by = Year]

您甚至可以在一行中完成所有工作

DT[,cohort := get(paste0("Age_",.GRP)),by = Year]

我希望它有所帮助

答案 1 :(得分:1)

以下是使用let regex = /(?!([A-Z]+))(\d+)(?=[A-Z]+)/g; let values = 'A32CZ, GH2X, ABC19E' let result = values.match(regex); console.log(result);

的选项
tidyverse