【问题标题】:R: Special case of merging two datasets by dateR:按日期合并两个数据集的特殊情况
【发布时间】:2021-11-02 03:06:06
【问题描述】:

我正在使用 R 分析来自动物收容所的数据。我有一个包含动物摄入量的数据集,以及另一个显示结果的数据集。我想合并这些数据集,以便每只动物的摄入信息和相应的结果信息都在同一行。

每个结果都有相应的较早摄入量。一些摄入量没有结果,因为这些动物仍在系统中。一只动物可以在系统中循环多次(例如,动物被送回收容所、领养、返回收容所、再次领养等)

数据框看起来像这样:

摄入量:

 Animal.ID Intake.Date Intake.Type
        A1  2016-01-01   Surrender
        A2  2017-01-01       Stray
        A1  2018-01-01   Surrender
        A3  2019-01-01       Stray
        A4  2020-01-01      Seized
        A5  2021-01-01   Surrender

结果:

 Animal.ID Outcome.Date Outcome.Type
        A1   2016-06-30     Adoption
        A2   2017-06-30   Euthanasia
        A1   2018-06-30     Transfer
        A3   2019-06-30     Adoption
        A5   2021-06-30     Transfer

在我的示例中,Animal.ID 为“A1”的动物在系统中循环了两次。 Animal.ID为“A4”的动物没有结果记录,因为该动物仍在收容所的照料下。

如何组合(合并)数据集,以使生成的数据集看起来像这样?

综合:

 Animal.ID Intake.Date Intake.Type Outcome.Date Outcome.Type
        A1  2016-01-01   Surrender   2016-06-30     Adoption
        A2  2017-01-01       Stray   2017-06-30   Euthanasia
        A1  2018-01-01   Surrender   2018-06-30     Transfer
        A3  2019-01-01       Stray   2019-06-30     Adoption
        A4  2020-01-01      Seized         <NA>         <NA>
        A5  2021-01-01   Surrender   2021-06-30     Transfer

我想这类问题在过去已经解决了,但我在运行 Google 搜索时一定没有使用正确的术语。

编辑:实际数据包含日期/时间(不仅仅是日期)。结果可能会在摄入后的几分钟内发生,也可能在数月后发生。

以下是创建这些示例数据集的代码:

intakes <- data.frame(
  Animal.ID = c("A1","A2","A1","A3","A4","A5"),
  Intake.Date = as.Date(c("2016-01-01","2017-01-01","2018-01-01","2019-01-01","2020-01-01","2021-01-01")),
  Intake.Type = c("Surrender","Stray","Surrender","Stray","Seized","Surrender")
)

outcomes <- data.frame(
  Animal.ID = c("A1","A2","A1","A3","A5"),
  Outcome.Date = as.Date(c("2016-06-30","2017-06-30","2018-06-30","2019-06-30","2021-06-30")),
  Outcome.Type = c("Adoption","Euthanasia","Transfer","Adoption","Transfer")
)

【问题讨论】:

    标签: r dataframe merge


    【解决方案1】:

    您需要创建一个新变量来匹配,因为数据集中没有足够的数据来确定每行的唯一匹配。看起来你想匹配Animal.ID,然后是入学年份,所以我创建了一个新变量year,两者都匹配,然后从最终数据集中删除它。当然,您可以将这个新变量设置为任何您想要包含更复杂情况的变量(例如,Intake on 12-31-2020,结果为 01-01-2021)。

    library(dplyr)
    library(lubridate)
    
    intakes %>%
      mutate(year = year(Intake.Date)) %>%
      left_join(mutate(outcomes, year = year(Outcome.Date)), by = c("Animal.ID", "year")) %>%
      select(-year)
    
      Animal.ID Intake.Date Intake.Type Outcome.Date Outcome.Type
    1        A1  2016-01-01   Surrender   2016-06-30     Adoption
    2        A2  2017-01-01       Stray   2017-06-30   Euthanasia
    3        A1  2018-01-01   Surrender   2018-06-30     Transfer
    4        A3  2019-01-01       Stray   2019-06-30     Adoption
    5        A4  2020-01-01      Seized         <NA>         <NA>
    6        A5  2021-01-01   Surrender   2021-06-30     Transfer
    

    【讨论】:

    • 不确定这是否可行。结果可能在摄入后一两个小时内发生 - 如果是对生病动物的安乐死请求,有时甚至更快。我只是在示例中使用了不同的年份以使其简单。在实际数据中,日期包括时间和日期。
    • 这种通用策略是合并这些数据集的唯一方法,因此您只需将答案扩展到您的特定用例。换句话说,如果每一行都没有唯一的标识符(或标识符的组合),则无法完成这种类型的合并。
    【解决方案2】:

    previous answer 是正确的,但不是按日期排序,我假设摄入量只与一个结果相关,除了给定动物的最近摄入量,它与零个或一个结果相关。

    因此,我建议在每个数据集中创建一个新变量,这是每只动物出现的(唯一)编号 (Animal.ID.occurrence),并在加入时使用它。

    library(dplyr)
    #> 
    #> Attaching package: 'dplyr'
    #> The following objects are masked from 'package:stats':
    #> 
    #>     filter, lag
    #> The following objects are masked from 'package:base':
    #> 
    #>     intersect, setdiff, setequal, union
    
    intakes <- data.frame(
        Animal.ID = c("A1","A2","A1","A3","A4","A5"),
        Intake.Date = as.Date(c("2016-01-01","2017-01-01","2018-01-01","2019-01-01","2020-01-01","2021-01-01")),
        Intake.Type = c("Surrender","Stray","Surrender","Stray","Seized","Surrender")
    )
    
    outcomes <- data.frame(
        Animal.ID = c("A1","A2","A1","A3","A5"),
        Outcome.Date = as.Date(c("2016-06-30","2017-06-30","2018-06-30","2019-06-30","2021-06-30")),
        Outcome.Type = c("Adoption","Euthanasia","Transfer","Adoption","Transfer")
    )
    
    intakes_occurrence <- intakes %>% group_by(Animal.ID) %>%
        arrange(Intake.Date) %>% 
        mutate(Animal.ID.occurrence = paste0(Animal.ID, ".", row_number())) %>% 
        ungroup()
    outcomes_occurrence <- outcomes %>% group_by(Animal.ID) %>%
        arrange(Outcome.Date) %>% 
        mutate(Animal.ID.occurrence = paste0(Animal.ID, ".", row_number())) %>% 
        ungroup() %>% 
        select(-Animal.ID) 
    
    intakes_occurrence %>% 
        full_join(outcomes_occurrence, by="Animal.ID.occurrence") %>% 
        select(-Animal.ID.occurrence)
    #> # A tibble: 6 × 5
    #>   Animal.ID Intake.Date Intake.Type Outcome.Date Outcome.Type
    #>   <chr>     <date>      <chr>       <date>       <chr>       
    #> 1 A1        2016-01-01  Surrender   2016-06-30   Adoption    
    #> 2 A2        2017-01-01  Stray       2017-06-30   Euthanasia  
    #> 3 A1        2018-01-01  Surrender   2018-06-30   Transfer    
    #> 4 A3        2019-01-01  Stray       2019-06-30   Adoption    
    #> 5 A4        2020-01-01  Seized      NA           <NA>        
    #> 6 A5        2021-01-01  Surrender   2021-06-30   Transfer
    

    reprex package 创建于 2021-09-05 (v2.0.1)

    已编辑以按日期排序。

    【讨论】:

    • 谢谢!我认为这行得通。我在实际数据集上尝试了你的方法。我还没有机会非常仔细地检查组合数据集,但在初步检查时它看起来是正确的。我永远不会自己想到这种方法。感谢您的帮助。
    • 抱歉,我说得太早了。您的方法确实匹配摄入量和结果,但日期并不总是正确排列。我看着一只在系统中循环八次的动物。合并后的数据集似乎将随机摄入与随机结果相匹配。有没有办法强制“group_by”函数根据摄入(或结果)日期进行分组?我认为这可能会解决问题。
    • 好的,如果输入数据没有按可能发生的日期排序。我已经添加了按日期显式排序,所以应该可以。 (我在帖子中编辑过)
    • 好的,您的修改版本似乎可以使用。我检查了四只在系统中循环多次的动物,摄入量和结果都正确匹配。再次感谢所有帮助。
    猜你喜欢
    • 2021-08-06
    • 2020-12-24
    • 2019-08-18
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    相关资源
    最近更新 更多