【问题标题】:Select most recent year and most complete row by date R按日期选择最近一年和最完整的行 R
【发布时间】:2020-12-03 15:47:46
【问题描述】:

我有一个时间序列数据,我试图在其中获取每个 ID 的最新有效响应。这是我的起始测试数据集:

dta <- data.frame(
  uniqueID = c("950513","950513", "950513","951634","951634", "951634","951640","951640", "951640",
               "951641","951641", "951641","951646","951646", "951646","952732","952732", "952732",
               "952895", "952895", "952895","952909","952909", "952909","952910","952910", "952910",
               "952911","952911", "952911"),
  year = c(2014, 2015, 2016, 2014, 2015, 2016, 2014, 2015, 2016, 2014, 2015, 2016, 2014, 2015, 2016,
           2014, 2015, 2016, 2014, 2015, 2016, 2014, 2015, 2016, 2014, 2015, 2016, 2014, 2015, 2016),
  var1 = c(2115, NA, 2115,NA, NA, NA, NA, 2903, NA, NA, 6040, 6040, 6103, 6103, 6268, 6511, 7101, 7101,
           7105, 7105, 7105,8901, 8520, 8901, 8540, 8540, NA, 8854, 2108, NA),
  var2 = c(2115, "", 2115,"", "", "", "", 2903, "", "", 6040, 6040, 6103, 6103, 6268, 6511, 7101, 7101,
           7105, 7105, 7105,8901, 8520, 8901, 8540, 8540, "", 8854, 2108, ""),
  var3 = c("turtle", "turtle", "turtle","", "tortoise","", "turtle", "", "", "", "turtle", "tortoise", 
           "tortoise", "tortoise", "", "", "turtle", "", "turtle", "tortoise", "turtle", "tortoise", "", "",
           "", "", "", "tortoise", "turtle", "tortoise"),
  var4 = c("", "", "", "", "", "", "", "yellow", "", "blue", "", "", "", "", "", "", "", "red", "red", "", "",
           "", "", "", "pink", "", "", "", "", "")
)

我希望每个 uniqueID 都有一个,我将在其中获得最新(按年份)的响应,其中包含所有列 var1-var4 的该 ID 的最完整信息。一步一步,这是我想做的:

  • 每个唯一ID 有一行输出
  • 默认情况下,选择最近一年(行)的响应(响应在 var1 - var4 中)
  • 如果最近一年的响应 (var1-var4) 有缺失值或空白,请忽略该 ID 的同一列中的不同值,必要时折叠年份。例如2014&2015

根据我的测试数据集,我希望数据集最终看起来像这样:

result <- data.frame(
  uniqueID = c("950513","951634","951640","951641","951646","952732","952895","952909","952910",
                       "952911"),
year = c("2016","2015","2015&2014","2016&2014", "2016&2015", "2016&2015", "2016&2014", "2016&2014", "2015&2014", "2016&2015" ),
var1 = c(2115,NA,2903, 6040, 6268, 7101, 7105, 8901, 8540, 2108),
var2 = c(2115,"", 2903, 6040, 6268, 7101, 7105, 8901, 8540, 2018),
var3 = c("turtle","tortoise", "turtle", "tortoise", "tortoise", "turtle", "turtle", "tortoise","", "tortoise"),
var4 = c("","", "yellow", "blue", "", "red", "red", "", "pink", "")
)

或者,年份可以拆分为多个列 year1、year2。

我使用 data.table 尝试了几种不同的解决方案,但这些解决方案通常专注于最近一年或最完整的案例,但不是两者兼而有之。如果需要,很乐意提供更多说明。

【问题讨论】:

    标签: r dplyr data.table


    【解决方案1】:

    应该这样做。

    is_valid <- function(x){
      !(x == "" | is.na(x))
    }
    valid_x <- function(x){
      if(any(is_valid(x))){
        x[which(is_valid(x))]
      }
      else{
        ""
      }
    }
    result <- dta %>% 
      mutate(across(contains("var"), as.character)) %>%
      pivot_longer(contains("var"), names_to="var", values_to="val") %>% 
      group_by(uniqueID, var) %>% 
      mutate(last_val = last(valid_x(val)), 
             last_year = max(year[which(val == last_val)])) %>%
      filter(year == last_year) %>% 
      ungroup %>% 
      group_by(uniqueID) %>% 
      mutate(last_year = paste(sort(unique(last_year[which(is_valid(last_val))]), decreasing=TRUE), collapse="&")) %>%
      select(-c(val, year)) %>% 
      pivot_wider(names_from="var", values_from="last_val") %>% 
      rename("year" = "last_year")
    
    result
    # # A tibble: 10 x 6
    # # Groups:   uniqueID [10]
    #   uniqueID year      var1  var2   var3       var4    
    #   <chr>    <chr>     <chr> <chr>  <chr>      <chr>   
    # 1 950513   2016      2115  "2115" "turtle"   ""      
    # 2 951634   2015      NA    ""     "tortoise" ""      
    # 3 951640   2015&2014 2903  "2903" "turtle"   "yellow"
    # 4 951641   2016&2014 6040  "6040" "tortoise" "blue"  
    # 5 951646   2016&2015 6268  "6268" "tortoise" ""      
    # 6 952732   2016&2015 7101  "7101" "turtle"   "red"   
    # 7 952895   2016&2014 7105  "7105" "turtle"   "red"   
    # 8 952909   2016&2014 8901  "8901" "tortoise" ""      
    # 9 952910   2015&2014 8540  "8540" ""         "pink"  
    # 10 952911   2016&2015 2108  "2108" "tortoise" ""      
    
    

    【讨论】:

    • 谢谢,这工作得相当好,但不适用于我想在多年内引入的带有 NA 的行。我也想将它们折叠成一行。关于如何做到这一点的任何想法?
    • @st2coker 我不确定你的意思。你能再解释一下吗?可以举个例子吗?
    • 我的真实数据集有防止行被折叠成一行的 NA。例如,输出是 2018&2019 年,但每个 ID 仍然包含两行,而不是每个 ID 一行。作为一种解决方法,我可以使用它,但只是想看看我是否可以合并到原始解决方案 result2 %>% group_by(uniqueID) %>% summarise_all(funs(first(na.omit(.))))
    • 你能发布一些显示问题的示例数据吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多