【问题标题】:R: Applying a function between two datesR:在两个日期之间应用函数
【发布时间】:2015-01-29 09:18:07
【问题描述】:

我有两个数据框,如下:
带有交易的数据框:tradeData(示例):

Login   OpenTime    CloseTime   Decision
859     13/01/2014  13/01/2014  1
859     16/01/2014  16/01/2014  1
859     21/01/2014  21/01/2014  1
859     21/01/2014  21/01/2014  1
859     22/01/2014  22/01/2014  1
859     23/01/2014  23/01/2014  1
859     27/01/2014  27/01/2014  1
859     03/02/2014  03/02/2014  1
859     04/02/2014  05/02/2014  1
859     07/02/2014  07/02/2014  1
859     11/02/2014  13/02/2014  1
939     06/02/2014  28/02/2014  1
939     06/02/2014  28/02/2014  1
939     06/02/2014  28/02/2014  1
1455    03/04/2014  03/04/2014  1
1455    04/04/2014  04/04/2014  1
1455    04/04/2014  07/04/2014  1
1455    08/04/2014  08/04/2014  1
1455    08/04/2014  08/04/2014  1
1455    09/04/2014  30/04/2014  1
1455    30/04/2014  30/04/2014  1

和另一个带有日期的数据框:datesData(示例):

Login       B_A        A_B
859     22/01/2014  23/01/2014
859     03/02/2014  07/02/2014
859     11/02/2014  12/02/2014
939     06/02/2014  01/01/2200
1455    04/04/2014  08/04/2014
1455    09/05/2014  30/06/2014

在 datesData 数据框中任何行的两个日期之间打开并与登录名匹配的任何交易(将是 tradeData 数据框中的一行)都应在决策列中收到 0。它必须在 B_A 列中的日期或之后打开,并且在 A_B 列中的日期之前打开。这个决策列预先填充了 1,所以我需要做的就是插入 0

生成的 tradeData 数据框如下所示:

Login   OpenTime    CloseTime   Decision
859     13/01/2014  13/01/2014  1
859     16/01/2014  16/01/2014  1
859     21/01/2014  21/01/2014  1
859     21/01/2014  21/01/2014  1
859     22/01/2014  22/01/2014  0
859     23/01/2014  23/01/2014  1
859     27/01/2014  27/01/2014  1
859     03/02/2014  03/02/2014  0
859     04/02/2014  05/02/2014  0
859     07/02/2014  07/02/2014  1
859     11/02/2014  13/02/2014  0
939     06/02/2014  28/02/2014  0
939     06/02/2014  28/02/2014  0
939     06/02/2014  28/02/2014  0
1455    03/04/2014  03/04/2014  1
1455    04/04/2014  04/04/2014  0
1455    04/04/2014  07/04/2014  0
1455    08/04/2014  08/04/2014  1
1455    08/04/2014  08/04/2014  1
1455    09/04/2014  30/04/2014  0
1455    30/04/2014  30/04/2014  1

因此,例如,tradeData 数据框中的第五行在 22/01/2014 和 23/01/2014 之前(datesDate 数据框中的第一行)打开并匹配该行中的登录,所以它收到一个 0。

任何帮助都会很棒!如果有任何不清楚的地方,请告诉我。

谢谢!

迈克

【问题讨论】:

  • 我可以建议使用?dput发布您的数据
  • @akrun 我现在去看看,谢谢
  • @RockScience,要做到这一点,我只需在控制台中输入dput 并复制粘贴结果吗?
  • 嗨,迈克,我的评论高于我的澄清答案。
  • @akrun,我正在努力使用 foverlaps 函数。这是我到目前为止所做的:colnames(datesData)[c(2:3)] = c("OpenTime","CloseTime")/setkey(datesData,"B_A","A_B")foverlaps(tradeData,datesData,by.tradeData = c("OpenTime","Closetime"),by.transferDates = c("OpenTime","CloseTime")) 但是,它不工作,我不知道如何解决它?

标签: r date


【解决方案1】:

一种方法是使用data.table 包:

library(data.table)

# convert to dates usefull columns
setDT(tradeData)
setkey(tradeData, Login)
tradeData[,OpenTime:=as.Date(OpenTime, format="%d/%m/%Y")]

# convert to dates usefull columns
df1 = datesData 
df1$B_A = as.Date(df1$B_A, format="%d/%m/%Y")
df1$A_B = as.Date(df1$A_B, format="%d/%m/%Y")

tradeData[,Decision:=sapply(OpenTime,function(d){ 
                          dt=df1[df1$Login==Login,]
                          as.integer(!any(d>=dt$B_A & d<dt$A_B))
                  }),
      by=Login]

结果如下:

> tradeData
    Login   OpenTime  CloseTime Decision
 1:   859 2014-01-13 13/01/2014        1
 2:   859 2014-01-16 16/01/2014        1
 3:   859 2014-01-21 21/01/2014        1
 4:   859 2014-01-21 21/01/2014        1
 5:   859 2014-01-22 22/01/2014        0
 6:   859 2014-01-23 23/01/2014        1
 7:   859 2014-01-27 27/01/2014        1
 8:   859 2014-02-03 03/02/2014        0
 9:   859 2014-02-04 05/02/2014        0
10:   859 2014-02-07 07/02/2014        1
11:   859 2014-02-11 13/02/2014        0
12:   939 2014-02-06 28/02/2014        0
13:   939 2014-02-06 28/02/2014        0
14:   939 2014-02-06 28/02/2014        0
15:  1455 2014-04-03 03/04/2014        1
16:  1455 2014-04-04 04/04/2014        0
17:  1455 2014-04-04 07/04/2014        0
18:  1455 2014-04-08 08/04/2014        1
19:  1455 2014-04-08 08/04/2014        1
20:  1455 2014-04-09 30/04/2014        1
21:  1455 2014-04-30 30/04/2014        1

【讨论】:

  • 这取决于您如何解释有点不清楚的作者条件(是每行比较行,如他所写,还是在所有行上 - 例如,一个日期可能优于 B_A 在某行,在另一个不同的行中低于 A_B)。
  • 好的,在你发表你的评论之前删除了我的评论,不应该使用关闭时间列来检查打开时间> 比 B_A 和关闭时间是
  • Ï如果您没看错,closeTime 列就不会被提及 :)
  • @ColonelBeauvel 嗨,感谢您的回答。我已经在我的数据子集上尝试过它,它似乎工作得很好。但是,我的数据集超过 500 万行,并且需要很长时间(运行了 20 分钟,仍未完成)。我有什么办法可以加快速度吗?再次感谢!
  • 你的 data.frame datesData 大吗?在这种情况下,最好在 data.table 中进行转换。
【解决方案2】:

这是一个使用 sqldf 包的等解决方案。

tradeData$OpenTime <- as.Date(trade.data$OpenTime, format="%d/%m/%Y")
datesData$B_A <- as.Date(datasData$B_A, format="%d/%m/%Y")
datesData$A_B <- as.Date(datasData$A_B, format="%d/%m/%Y")

sqldf(c("UPDATE tradeData
      SET Decision = 0
      WHERE EXISTS (SELECT * FROM datesData WHERE
                      tradeData.Login = datesData.Login AND
                      tradeData.OpenTime >= datesData.B_A  AND
                      tradeData.OpenTime < datesData.A_B)",
      "SELECT * FROM tradeData"))

#    Login   OpenTime  CloseTime Decision
# 1    859 2014-01-13 13/01/2014        1
# 2    859 2014-01-16 16/01/2014        1
# 3    859 2014-01-21 21/01/2014        1
# 4    859 2014-01-21 21/01/2014        1
# 5    859 2014-01-22 22/01/2014        0
# 6    859 2014-01-23 23/01/2014        1
# 7    859 2014-01-27 27/01/2014        1
# 8    859 2014-02-03 03/02/2014        0
# 9    859 2014-02-04 05/02/2014        0
# 10   859 2014-02-07 07/02/2014        1
# 11   859 2014-02-11 13/02/2014        0
# 12   939 2014-02-06 28/02/2014        0
# 13   939 2014-02-06 28/02/2014        0
# 14   939 2014-02-06 28/02/2014        0
# 15  1455 2014-04-03 03/04/2014        1
# 16  1455 2014-04-04 04/04/2014        0
# 17  1455 2014-04-04 07/04/2014        0
# 18  1455 2014-04-08 08/04/2014        1
# 19  1455 2014-04-08 08/04/2014        1
# 20  1455 2014-04-09 30/04/2014        1
# 21  1455 2014-04-30 30/04/2014        1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 2022-01-01
    • 2012-12-24
    • 2014-12-11
    • 2012-10-13
    • 1970-01-01
    • 2010-11-25
    相关资源
    最近更新 更多