根据ID,开始年份和持续时间创建新数据框

时间:2018-04-04 05:27:39

标签: r

问题的标题可能不完全准确,但我不知道如何描述它。所以考虑一个基本数据集:

Name YearBegin YearEnd Duration

Ryan   1988     1989      2

AJ     1990     1991      3

我想将其转换为:

Name Year Duration

Ryan 1988    1

Ryan 1989    2

AJ   1990    1

AJ   1991    2

AJ   1992    3
你能指点一下吗?我不太清楚从哪里开始。

3 个答案:

答案 0 :(得分:0)

我做了两个假设,第一个是旧数据框被称为df,而你的年份和持续时间变量是数字(如果不是这样,请我们df$variables <- as.numeric(df$variables)调整)。

另一个假设是AJ应该在1992年结束这一年(而不是你现在拥有的1991年)。这不会影响我的解决方案(我只使用持续时间和YearBegin),但我想我会指出它,以防它有一些我没有意识到的意义。

repsapply的一些巧妙用法可以满足您的需求:)

df2 <- data.frame(
  Name = rep(df$Name, times = df$Duration),
  Year = rep(df$YearBegin, times = df$Duration) + unlist(sapply(df$Duration, function(x){1:x})),
  Duration =  unlist(sapply(df$Duration, function(x){0:(x-1)}))
)

分解每一行:

Name = rep(df$Name, times = df$Duration)重复该名称,每个名称都以相应的持续时间重复。

接下来我将解释这一点,然后回到Year

Duration = unlist(sapply(df$Duration, function(x){1:x}))使用sapply将函数1:x应用于Duration的每个元素。因此,它需要每个Duration并生成一个从1开始的序列。

Year = rep(df$YearBegin, times = df$Duration) + unlist(sapply(df$Duration, function(x){0:(x-1)}))利用相同的Duration计算,并将这些数字添加到开始年份(利用与重复名称相同的过程)。唯一的区别是持续时间中的元素被移动了一个因此我们只在第一年添加0,依此类推。基本上这些数字可以正常运行:)

将它们全部绑定到数据框中,就可以获得所需内容!

  Name Year Duration
1 Ryan 1988        1
2 Ryan 1989        2
3   AJ 1990        1
4   AJ 1991        2
5   AJ 1992        3

答案 1 :(得分:0)

正如Dan Hall在评论中指出的那样, RJ 行的YearEnd应为1992

我假设必须对问题进行上述修正

我正在使用循环来获得答案。所以,我的回答可能不是正确的“R”方式。但是,这很简单,而且很有效。 其他人可能会想出更好的方法。

尝试以下方法 -

#Create the sample data
df1 <- data.frame(Name = c("Ryan","AJ"),YearBegin = c(1988,1990),YearEnd = c(1989,1992),Duration = c(2,3))
#Dummy data frame to append the results
df2 <- data.frame(Name = character(),Year = integer(), Duration = integer())
#Loop for each name
for( i in 1:nrow(df1)){
  Name <- df1$Name[i]
  Year <- df1$YearBegin[i]
#Loop for each year
  for(j in 1:df1$Duration[i]){
#The variable j is used to manipulate the Year column
    temp_row <- data.frame(Name = Name,Year = Year+(j-1),Duration = j) 
    df2 <- rbind(df2,temp_row)
  }
}

#Output
print(df2)
# Name Year Duration
# 1 Ryan 1988        1
# 2 Ryan 1989        2
# 3   AJ 1990        1
# 4   AJ 1991        2
# 5   AJ 1992        3

希望这很清楚。

答案 2 :(得分:0)

我喜欢使用data.table包进行这些争论。

这是我的解决方案:

假设AJ1992结束,我们的数据集df为:

df<-read.table(text='Name YearBegin YearEnd Duration    
Ryan   1988     1989      2    
AJ     1990     1992      3', header=T)

将其变为data.table

require(data.table)
df<-as.data.table(df)

使用一行:

df[, .(Year = seq(YearBegin, YearEnd, 1),
       Duration = 1:(1 + YearEnd - YearBegin)), by = Name]

理念是:按名称分组,并且您需要每年编号的序列,从YearBeginYearEnd1

Duration1到总长度,等于(1 + YearEnd - YearBegin)

输出:

   Name Year Duration
1: Ryan 1988        1
2: Ryan 1989        2
3:   AJ 1990        1
4:   AJ 1991        2
5:   AJ 1992        3

希望这有帮助