R:如何根据使用函数的条件将一个数据框中的值替换为另一个数据框?

时间:2017-11-07 11:14:03

标签: r function date dataframe match

目标:将日期从一个数据框映射到另一个数据框,因为它处于特定日期间隔内。例如,假设我们需要在2017年12月20日至2017年12月25日或2017年12月26日至2017年12月30日的时间间隔内提供礼品,并收到礼品发件人的回复。 2017年12月23日。我想创建一个函数,可以根据它所在的日期间隔来确定响应日期的放置位置。在上面的示例中,响应日期将在2017年12月20日至2017年12月25日期间。 注意:下面的“匹配”一词表示从一个数据框到另一个数据框满足某个条件。

以下是一些示例代码,用于演示我的意思。

# Creating the Data Frame with a start and end date interval
StartDate <- seq(as.Date("2000/1/1"), by = "month", length.out = 10)

EndDate <- StartDate +7

Dates_Interval <- data.frame(StartDate,EndDate)

# Creating a second data frame with the response dates only 
ResponseDate <- seq(as.Date("2000/1/6"), by = "month", length.out = 10)

Response_Substitute <- data.frame(ResponseDate)
# Substituting random NA values 
Response_Substitute[c(1,5,8),] <- NA


# > Response_Substitute 
#     ResponseDate
#    1          <NA>
#    2    2000-02-09
#    3    2000-03-06
#    4    2000-04-06
#    5          <NA>
#    6    2000-06-06
#    7    2000-07-06
#    8          <NA>
#    9    2000-09-06
#    10   2000-10-06

# Creating a function which evaluates a value in data frame two             
# (Response_Substitute) and checks 
# whether it meets
# a condition in Dates_Interval. 

dateresponses <- function(x,y,z) {
  sub_date <- ifelse ( y <=x && x <= z, x, NA)
  converteddate <- as.Date(sub_date, origin = "1899-12-30")
  return(converteddate)
}
# Example of the function in use to show how it matches a certain condition. 
x <- Response_Substitute[2,1] 
b <- dateresponses(x,Dates_Interval[2,1],Dates_Interval[2,2])


# > b
# [1] "1930-02-04"

# Example of the function in use to show when a response date does not 
# match a certain condition
   x <- Response_Substitute[2,1] <- as.Date("2000/2/9")
   b <- dateresponses(x,Dates_Interval[2,1],Dates_Interval[2,2])
# > b
#  [1] NA

# Example of the function in use to show when there is no response date in      
# the Response_Substitute variable 
   x <- Response_Substitute[1,1] 
   b <- dateresponses(x,Dates_Interval[2,1],Dates_Interval[2,2])
# > b
#  [1] NA

我需要一个能够在Dates_Interval数据框中创建新列的功能,该列与响应日期相匹配,其日期间隔来自StartDateEndDate列。如果没有匹配,则如果没有响应,则响应将为NA。如果有响应,响应日期不会落入任何时间间隔,那么我希望创建一个能够捕获不匹配响应的数据帧。

这是最终数据框的样子:

Dates_Interval$ResponseDate <- Response_Substitute
     # > Dates_Interval
   # StartDate    EndDate ResponseDate
# 1  2000-01-01 2000-01-08         <NA>
# 2  2000-02-01 2000-02-08   2000-02-06
# 3  2000-03-01 2000-03-08   2000-03-06
# 4  2000-04-01 2000-04-08   2000-04-06
# 5  2000-05-01 2000-05-08         <NA>
# 6  2000-06-01 2000-06-08   2000-06-06
# 7  2000-07-01 2000-07-08   2000-07-06
# 8  2000-08-01 2000-08-08         <NA>
# 9  2000-09-01 2000-09-08   2000-09-06
# 10 2000-10-01 2000-10-08   2000-10-06

对于 NA但不匹配任何时间间隔的响应日期,可以像这样创建另一个数据帧:

Unmatched_Response_Date <- data.frame(seq(as.Date("2000/1/9"), by = "month", 
length.out = 2))

colnames(Unmatched_Response_Date) <- "Unmatched Responses"

Unmatched_Response_Date
# > Unmatched_Response_Date
# Unmatched Responses
# 1          2000-01-09
# 2          2000-02-09

修改: 使用dateresponses函数时,我注意到了一些错误。当我使用Response_substitute数据框中的日期时。日期的输出与数据框不同。例如对于Response_substitute[2,1],该值应为2000-02-09,但我得1930-02-04。还有什么想法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

以下是您提供的代码:

StartDate <- seq(as.Date("2000/1/1"), by = "month", length.out = 10)
EndDate <- StartDate +7
Dates_Interval <- data.frame(StartDate,EndDate)
# Creating a second data frame with the response dates only 
ResponseDate <- seq(as.Date("2000/1/6"), by = "month", length.out = 10)
Response_Substitute <- data.frame(ResponseDate)
# Substituting random NA values 
Response_Substitute[c(1,5,8),] <- NA

所以为了回答你的问题,我添加了另一个日期列,以便我们在两个data.frames中都有一个间隔。我还从包含响应的第一个data.frame中删除了NA值。这些似乎与您的预期产量无关。纠正我,如果错了。

Response_Substitute$Date2 <- Response_Substitute$ResponseDate - 1
Response_Substitute <- Response_Substitute[!is.na(Response_Substitute$ResponseDate),]

这个问题的关键在于使用名为foverlaps()的data.table函数。从文档中,这是一个快速重叠连接功能。它旨在找到两个间隔重叠的位置并将数据连接在一起。下面的代码就是这样。

这也是我需要在Response_Substitute中生成另一个日期的原因。 foverlaps()需要两个时间间隔才能正常工作。

library(data.table)
Dates_Interval <- as.data.table(Dates_Interval)
Response_Substitute <- as.data.table(Response_Substitute)
setkey(Response_Substitute, Date2, ResponseDate)
join_df <- foverlaps(Dates_Interval, Response_Substitute, 
          by.x = c('StartDate', 'EndDate'))

输出:

   ResponseDate      Date2  StartDate    EndDate
 1:         <NA>       <NA> 2000-01-01 2000-01-08
 2:   2000-02-06 2000-02-05 2000-02-01 2000-02-08
 3:   2000-03-06 2000-03-05 2000-03-01 2000-03-08
 4:   2000-04-06 2000-04-05 2000-04-01 2000-04-08
 5:         <NA>       <NA> 2000-05-01 2000-05-08
 6:   2000-06-06 2000-06-05 2000-06-01 2000-06-08
 7:   2000-07-06 2000-07-05 2000-07-01 2000-07-08
 8:         <NA>       <NA> 2000-08-01 2000-08-08
 9:   2000-09-06 2000-09-05 2000-09-01 2000-09-08
10:   2000-10-06 2000-10-05 2000-10-01 2000-10-08

最后一步是删除列,并生成不匹配的空向量。

# Removes the Date2 Column
join_df[, Date2:=NULL] 
# Generate list of responses that didn't join
setdiff(Response_Substitute$ResponseDate, join_df$ResponseDate) 

这适用于您的问题吗? 进一步阅读:12