【问题标题】:Generalise a function to vector format data.table将函数泛化为矢量格式 data.table
【发布时间】:2021-12-06 06:36:39
【问题描述】:

我有以下数据结构,我想逐行插入数据直到某一年:

require('data.table')
test_dt <- data.table(iso1 = c('BTN', 'IND', 'BGD'),
 iso2 = c('AFG', 'AFG', 'AFG'),
 year = c(2006, 2003, 2006))

我想出了以下函数,它适用于单行情况,但不适用于一般情况:

interpolate_rows <- function(dt, stop_year = 2008)  {
  
    year <- as.integer(dt[, .SD, .SDcols = 'year'])
    
    # If year is less than stop year, fill in observations:
    if (year < stop_year) {
      time_delta <- seq(year, stop_year)
            
      # Explode bilateral country observation:
      dt <- dt[rep(dt[, .I], length(time_delta))]
      
      # Replace year column w/ time_delta sequence:
      dt <- dt[, year := time_delta]
      }
    
  return(dt)
}
## Output
bar <- interpolate_rows(test_dt[1])

bar
  iso1  iso2   year
 1:  BTN    AFG    2006
 2:  BTN    AFG    2007
 3:  BTN    AFG    2008

我想要的是:

bar <- interpolate_rows(test_dt)

bar
  iso1  iso2   year
 1:  BTN    AFG    2006
 2:  BTN    AFG    2007
 3:  BTN    AFG    2008
 6:  IND    AFG    2003
 7:  IND    AFG    2004
 8:  IND    AFG    2005
 9:  IND    AFG    2006
 10:  IND    AFG    2007
 11:  IND    AFG    2008
 14:  BGD    AFG    2006
 14:  BGD    AFG    2007
 14:  BGD    AFG    2008

我知道罪魁祸首很可能是这条线 @ 987654325@,但我不知道如何用它代替工作矢量解决方案。我尝试在interpolate_rows() 中嵌套一个lapply() 函数来提取每个独特组的年份并使用Map(),但这些都没有产生有效的解决方案。

任何帮助我找到可行的矢量解决方案,将不胜感激。

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    简单地使用by怎么样:

    test_dt[, .(year = min(year):stop_year), by = .(iso1, iso2)]
    
    #     iso1 iso2 year
    #  1:  BTN  AFG 2006
    #  2:  BTN  AFG 2007
    #  3:  BTN  AFG 2008
    #  4:  IND  AFG 2003
    #  5:  IND  AFG 2004
    #  6:  IND  AFG 2005
    #  7:  IND  AFG 2006
    #  8:  IND  AFG 2007
    #  9:  IND  AFG 2008
    # 10:  BGD  AFG 2006
    # 11:  BGD  AFG 2007
    # 12:  BGD  AFG 2008
    

    【讨论】:

      【解决方案2】:

      一种使用dplyrtidyr 库的方法。

      library(dplyr)
      library(tidyr)
      
      interpolate_rows <- function(dt, stop_year = 2008)  {
        dt %>%
          group_by(iso1, iso2) %>%
          complete(year = year : stop_year) %>%
          ungroup
      }
      
      interpolate_rows(test_dt)
      
      #  iso1  iso2   year
      #   <chr> <chr> <dbl>
      # 1 BGD   AFG    2006
      # 2 BGD   AFG    2007
      # 3 BGD   AFG    2008
      # 4 BTN   AFG    2006
      # 5 BTN   AFG    2007
      # 6 BTN   AFG    2008
      # 7 IND   AFG    2003
      # 8 IND   AFG    2004
      # 9 IND   AFG    2005
      #10 IND   AFG    2006
      #11 IND   AFG    2007
      #12 IND   AFG    2008
      

      另一种方式-

      library(data.table)
      
      interpolate_rows <- function(dt, stop_year = 2008)  {
        vals <- seq(dt$year, stop_year)
        dt[rep(1, length(vals))][, year := vals]
      }
      
      rbindlist(by(test_dt, seq(nrow(test_dt)), interpolate_rows))
      

      【讨论】:

        猜你喜欢
        • 2023-03-14
        • 2014-03-31
        • 1970-01-01
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多