【问题标题】:Add rows to dataframe based on existing rows根据现有行向数据框添加行
【发布时间】:2016-02-18 08:05:39
【问题描述】:

我有这个数据框:

df <- data.frame(group=c("A", "A", "B", "B"), year=c(1980, 1986, 1990, 1992))
  group year
1     A 1980
2     A 1986
3     B 1990
4     B 1992

我想通过以下方式修改它:

  • 为每个现有行添加前两年的行
  • 添加一个带有相应年份变量的新列
  • 删除现有行

这将是结果:

   group  year     pre
1      A  1978 pre1980
2      A  1979 pre1980
3      A  1984 pre1986
4      A  1985 pre1986
5      B  1988 pre1990
6      B  1989 pre1990
7      B  1990 pre1992
8      B  1991 pre1992

添加新列会很容易..

df$pre <- paste("pre", df$year, sep="")

但我不知道如何添加相应年份的新行(当然,创建一个全新的数据框也一样好)。有什么提示吗?

【问题讨论】:

  • do.call('rbind', lapply(1:nrow(df), function(x) {x &lt;- df[x, ]; data.frame(group = x$group, year = x$year - 2:1, pre = paste0('pre', x$year))}))

标签: r dataframe


【解决方案1】:

base Rftw:

data.frame(group = rep(df$group, each=2),
           year = df[rep(1:nrow(df), each=2),]$year-2:1,
           pre = paste0("pre",rep(df$year,each=2)))
#   group year     pre
# 1     A 1978 pre1980
# 2     A 1979 pre1980
# 3     A 1984 pre1986
# 4     A 1985 pre1986
# 5     B 1988 pre1990
# 6     B 1989 pre1990
# 7     B 1990 pre1992
# 8     B 1991 pre1992

【讨论】:

    【解决方案2】:

    使用 data.table 包,这是一种方法。有了给定的数据,我决定使用年份作为组变量。对于每一年,我计算前两年并用当年创建 pre****。有两个年份的专栏,所以最后我删除了其中一个。

    setDT(df)[, list(group = group,
                     year = c((year - 2), (year - 1)),
                     pre = paste0("pre", year, collapse = "")), by = "year"][, -1, with = FALSE][]
    
    #   group year     pre
    #1:     A 1978 pre1980
    #2:     A 1979 pre1980
    #3:     A 1984 pre1986
    #4:     A 1985 pre1986
    #5:     B 1988 pre1990
    #6:     B 1989 pre1990
    #7:     B 1990 pre1992
    #8:     B 1991 pre1992
    

    如果同一年份出现两次以上,您将执行以下操作。这个新的数据框出现了两次 1992。

    df <- data.frame(group=c("A", "A", "B", "B"), year=c(1980, 1986, 1992, 1992))
    
    
    setDT(df)[, list(group = group,
                     year = c((year - 2), (year - 1)),
                     pre = paste0("pre", year, collapse = "")), by = rownames(df)][, -1, with = FALSE]
    
    
    #   group year     pre
    #1:     A 1978 pre1980
    #2:     A 1979 pre1980
    #3:     A 1984 pre1986
    #4:     A 1985 pre1986
    #5:     B 1990 pre1992
    #6:     B 1991 pre1992
    #7:     B 1990 pre1992
    #8:     B 1991 pre1992
    

    【讨论】:

    • 谢谢,根据我的真实数据,第一个选项给了我一个我不明白的警告:Column 2 of result for group 2 is length 3 but the longest column in this result is 4. Recycled leaving remainder of 1 items. This warning is once only for the first group with this issue.,我认为第二个选项效果很好!
    • @beetroot 由于我没有您的数据,恐怕我无法看到您这边发生了什么。如果第二个选项适合您,那就太好了。你现在有另一个答案。因此,您可以选择解决问题。 :)
    • 选项太多 ;) 我希望你不介意我接受 Pierre Lafortune 的回答。我只是从来没有真正使用过数据表包..
    • @beetroot 不用担心。很高兴为您提供帮助。
    【解决方案3】:

    这是Map的另一个选项

    do.call(rbind,Map(function(x,y,z) 
       data.frame(group=x, year=y:z, pre=paste0('pre', z+1)), 
        df$group, df$year-2, df$year-1))
    #  group year     pre
    #1     A 1978 pre1980
    #2     A 1979 pre1980
    #3     A 1984 pre1986
    #4     A 1985 pre1986
    #5     B 1988 pre1990
    #6     B 1989 pre1990
    #7     B 1990 pre1992
    #8     B 1991 pre1992
    

    或者用rep修改

    `row.names<-`(transform(df[rep(1:nrow(df),each=2),],
          year = year-2:1, pre = paste0('pre', year) ), NULL)
    #  group year     pre
    #1     A 1978 pre1980
    #2     A 1979 pre1980
    #3     A 1984 pre1986
    #4     A 1985 pre1986
    #5     B 1988 pre1990
    #6     B 1989 pre1990
    #7     B 1990 pre1992
    #8     B 1991 pre1992
    

    【讨论】:

      【解决方案4】:

      如果你不挖掘最终订单,没有额外的库你可以使用

      gap = function(df, y) transform(df, year=year-y, pre = sprintf("pre%d", year))
      rbind(gap(df,2), gap(df,1))
      

      【讨论】:

        【解决方案5】:

        这是一个没有包的简单解决方案:

        您的数据框:

        df <- data.frame(group=c("A", "A", "B", "B"), year=c(1980, 1986, 1990, 1992))
        
        group year
        1     A 1980
        2     A 1986
        3     B 1990
        4     B 1992
        

        减去两年并添加列前:

        df1<-cbind(group=as.character(df$group),year=df$year-2, pre=paste("pre",df$year,sep=""))
        
        group year   pre      
        [1,] "A"   "1978" "pre1980"
        [2,] "A"   "1984" "pre1986"
        [3,] "B"   "1988" "pre1990"
        [4,] "B"   "1990" "pre1992"
        

        接下来减去 1 年并添加列 pre:

        df2<-cbind(group=as.character(df$group),year=df$year-1,pre=paste("pre",df$year,sep=""))
        
            group year   pre      
        [1,] "A"   "1979" "pre1980"
        [2,] "A"   "1985" "pre1986"
        [3,] "B"   "1989" "pre1990"
        [4,] "B"   "1991" "pre1992"
        

        现在rbind两人在一起:

        ndf<-data.frame(rbind(df1,df2))
        
        group year     pre
        1     A 1978 pre1980
        2     A 1984 pre1986
        3     B 1988 pre1990
        4     B 1990 pre1992
        5     A 1979 pre1980
        6     A 1985 pre1986
        7     B 1989 pre1990
        8     B 1991 pre1992
        

        按照year排序。这是你的输出。

        Lastdf <- ndf[order(ndf$year),] 
        
        group year     pre
        1     A 1978 pre1980
        5     A 1979 pre1980
        2     A 1984 pre1986
        6     A 1985 pre1986
        3     B 1988 pre1990
        7     B 1989 pre1990
        4     B 1990 pre1992
        8     B 1991 pre1992
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-01-07
          • 1970-01-01
          • 1970-01-01
          • 2021-06-20
          • 2015-11-19
          • 1970-01-01
          • 2019-11-12
          相关资源
          最近更新 更多