【问题标题】:Append a date to a data frame based on a condition根据条件将日期附加到数据框
【发布时间】:2021-06-06 18:03:19
【问题描述】:

我有两个具有共同 ID(员工编号)的数据集。

数据集 1 是所有员工的列表以及他们加入我公司的日期。它们可以在此数据集中合法地复制,因为它们可以在以后返回公司。

在数据集 2 中,我列出了向储蓄计划付款的所有员工以及交易日期。同样,由于付款超过 1 次,可能会出现重复

我正在尝试将两个数据集合并在一起,以便将来自 Dataset2 的日期附加到 Dataset 1 中的“正确”行。我的意思是附加到他们所在职位的就业记录他们付款的时间。

我已经按照此解决方案查看了加入日期,但我的数据集 1 中存在重复项意味着这不起作用 Data.table: Join on ID and Date key, but want closest date before (or equal to ) date key in first table

数据集 1 中的示例数据如下所示

Employee    JoinDate
001         01/01/2019
002         01/03/2019
003         01/08/2019
004         01/01/2019
001         01/10/2020
003         01/04/2020
005         01/04/2019
001         01/01/2021
004         01/08/2020
003         01/10/2020

数据集 2 中的示例数据

Employee    PayDate
001         01/11/2020
002         01/04/2019
003         01/05/2020
003         01/12/2020
004         01/05/2019
004         01/10/2020
005         01/10/2019

员工可以多次付款,因此问题在于将每笔付款标记到正确的就业记录中。加入后必须付款。

对于这个虚拟数据,期望的输出是:

Employee    JoinDate     PayDate
001         01/10/2020   01/11/2019
002         01/03/2019   01/04/2019
003         01/04/2020   01/05/2020
003         01/10/2020   01/12/2020
004         01/01/2019   01/05/2019
004         01/08/2020   01/10/2020
005         01/04/2019   01/10/2019

【问题讨论】:

  • 嗨。例如,请使用 dput(head(df, 10)) 来提供您的数据样本而不是截图。

标签: r


【解决方案1】:

tidyverse 接近。感谢@SEAnalyst 创建toy_data

library(tidyverse)

Dataset1 %>% full_join(Dataset2) %>%
  mutate(across(!Employee, ~as.Date(., format = '%d/%m/%Y'))) %>%
  filter(JoinDate < PayDate) %>%
  group_by(Employee, PayDate) %>%
  slice_tail()

#> Joining, by = "Employee"
#> # A tibble: 7 x 3
#> # Groups:   Employee, PayDate [7]
#>   Employee JoinDate   PayDate   
#>   <chr>    <date>     <date>    
#> 1 001      2020-10-01 2020-11-01
#> 2 002      2019-03-01 2019-04-01
#> 3 003      2020-04-01 2020-05-01
#> 4 003      2020-10-01 2020-12-01
#> 5 004      2019-01-01 2019-05-01
#> 6 004      2020-08-01 2020-10-01
#> 7 005      2019-04-01 2019-10-01

reprex package (v2.0.0) 于 2021-06-06 创建

【讨论】:

  • 简单漂亮!我在想我会将我的答案重写为 sapply() 的函数或在 Rcpp 中实现 for 循环,但现在我不会打扰了。
  • 感谢您的解决方案。不幸的是,这不起作用 - 错误“找不到功能”。我正在使用 R 3.6.1 - 也许它太旧了?另外,我只是在我的示例中编造了一些数据(我不喜欢将真实数据放在这里,因为它是商业的)。我的日期格式正确,已经是 m/d/Y。考虑到这一点,我可以简单地将 ~ as.Date 语句放在 mutate 行中吗?
  • 好的 - 我已经完全放弃了 mutate 行。现在它告诉我“找不到函数 slice_tail()”
  • 你加载了tidyverse吗?你用的是什么版本? @Nottles82
【解决方案2】:

这是如何在 for 循环中实现的。

#Your data
Dataset1<- data.frame(
Employee    = c("001",   "002",  "003",  "004",  "001", "003", "005","001" ,"004", "003") ,       
JoinDate =c("01/01/2019","01/03/2019","01/08/2019","01/01/2019","01/10/2020","01/04/2020","01/04/2019","01/01/2021","01/08/2020","01/10/2020"))

Dataset2<-data.frame(
 Employee =c("001" ,        "002" ,       "003" ,        "003" ,        "004" ,       "004",        "005"),      
PayDate = c("01/11/2020","01/04/2019","01/05/2020","01/12/2020","01/05/2019","01/10/2020","01/10/2019"))


#make properly formated dates
Dataset1$JoinDate<-as.Date(Dataset1$JoinDate, "%m/%d/%Y")
Dataset2$PayDate<-as.Date(Dataset2$PayDate, "%m/%d/%Y")

library(dplyr)    
#Make an empty vector equal to the length of the eventual end result. 
my_matches<-vector(mode = "list", length = nrow(Dataset2))

for(i in 1:nrow(Dataset2)){
#Get the index of matching employees
employee_index<- which(Dataset2$Employee[i]== Dataset1$Employee)
#Find/filter dates greater or equal to hire date
filter_new_hire_dates<-Dataset2$PayDate[i] >= Dataset1$JoinDate[employee_index]
#Then get the index of the max hire date of those remaining hire dates
join_index<-employee_index[which.max(Dataset1$JoinDate[employee_index] [filter_new_hire_dates])]
#Join and save to list
my_matches[[i]]<-dplyr::inner_join(Dataset2[i,],Dataset1[join_index,])
}

#contvert to dataframe if that is what you want
Dataset3 <- dplyr::bind_rows(my_matches)

【讨论】:

  • 谢谢 - 我担心在这里使用循环。我有(在这个特定的例子中)大约 120k 条记录,这需要一些时间来使用循环进行处理,但是,如果我能让逻辑正常工作,我想将它应用于一组非常相似的数据,它有数百万个观察值
  • 我对原始代码做了一些小的修改,希望能提高你的速度。
猜你喜欢
  • 2023-01-21
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
  • 2017-02-06
  • 2022-10-13
  • 1970-01-01
相关资源
最近更新 更多