【问题标题】:R: How to substitute a value from one dataframe to another based on a condition using a function?R:如何使用函数根据条件将一个数据帧中的值替换为另一个数据帧?
【发布时间】:2017-11-07 11:14:03
【问题描述】:

目标: 将日期从一个数据帧映射到另一个数据帧,前提是它属于某个日期间隔。例如,假设我们需要在 20/12/2017 到 25/12/2017 或 26/12/2017 到 30/12/2017 的时间间隔内送出礼物,然后收到礼物发送者的回复2017 年 12 月 23 日。我想创建一个函数,该函数可以根据响应日期所在的日期间隔确定放置响应日期的位置。在上面的示例中,响应日期将在 20/12/2017 到 25/12/2017 之间。 注意:下面的术语“匹配”是指一个数据帧与另一个数据帧满足某个条件。

这里有一些示例代码来说明我的意思。

# 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

对于 not 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。还有解决这个问题的想法吗?

【问题讨论】:

  • 为什么不在函数的ifelse 中使用NA 而不是"N/A"?这将返回 NA 而不是您的错误示例的错误消息。
  • @LAP 这是一个很好的观点!我会将其更改为代码以解决限制问题。这可以帮助我们解决整体问题,谢谢。
  • stackoverflow.com/questions/21560500/…。那似乎有类似的想法。如果您愿意,我可以针对您的特定问题写回复。
  • @jacobsg 我看了你发给我的链接,看看我能用它做什么。不过,如果您能对我的特定问题做出回应,那仍然很棒。非常感谢!

标签: r function date dataframe match


【解决方案1】:

这是您提供的代码:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    相关资源
    最近更新 更多