用于启用类型调度的习惯用法

时间:2017-11-22 22:08:53

标签: r class date date-range dispatch

这里有几个问题,如果其中任何一个得到足够好的回答,我会感到满意。

背景 - 最终目标是什么?

我有兴趣在R中表示日期范围。最小要求是我们代表一个开始和结束日期,可以使用长度为二的日期向量轻松完成。另外,将此对象扩展为更进一步的类

会更好
  • 为每个范围(即字符串)提供名称
  • 可以(轻松)使用dplyr::between运算符

我以前的方法的缺点

我之前将每个范围表示为长度为二的日期向量。这里的优点是我不依赖任何外部依赖,我的数据结构非常轻巧,所以编程并不麻烦。缺点是我已经厌倦了通过beg运算符和参数end以及{{1}访问日期范围的[1分别(可解释的比我们有类实现时更难解释)。

此外,我们最终处理一系列日期范围(即向量),因此在开始嵌套数据结构之前抽象出2是有帮助的。我不想使用长度为两个日期向量的列表,也不希望使用带有两行的data.frame,每列被解释为日期范围。

我在哪里看?

我查看了DateRange包并考虑从lubridate类继承。从这个继承开始的缺点是我不认为S4对我的用例是必要的。我只需要一些简单的数据属性和一个很好的API来调用Interval

理想的解决方案可能只是扩展dplyr::between类以保存名称,结束日期(可能是此信息已通过lubridate::Interval存储在Interval中的方法),并扩展{{1}与上课一起玩得很好。

我尝试了什么?

这是我正在寻找的一个粗略的实现:

@start + @.Data

现在,我希望能够重载dplyr::between运算符,以便我可以按如下方式调用它:# 3 key attributes: beg, end, and name. MyInterval <- function(beg, end, name = NULL) { if (class(beg) == "character") beg <- as.Date(beg) if (class(end) == "character") end <- as.Date(end) if (is.null(name)) name <- as.character(beg) structure(.Data = list('beg' = beg, 'end' = end, 'name' = name), class = "MyInterval") } ,我们注意到between需要三个参数。为了尝试实现这一点,我尝试按如下方式设置类型调度:

between(x, MyInterval)

我选择在dplyr::between(x, lo, hi)原型中使用between <- function(...) UseMethod('between') between.MyInterval <- function(interval, x) { if (class(x) == "character") x <- as.Date(x) dplyr::between(x, interval$beg, interval$end) } between.default <- function(x, lo, hi) dplyr::between(x, lo, hi) 的原因是...between之间的参数顺序目前不同。有没有更好的方法来编写这个?我相信这种行为符合预期(乍一看)

between.MyInterval

谢谢

欢迎任何批评。我知道between.default是一个无法开箱即用的函数,因此我自己实现这一功能会产生代码味道。

1 个答案:

答案 0 :(得分:2)

可能使用data.table&#39; s inrange - 函数。

首先,让我们做一个间隔:

my.interval <- function(beg, end) data.table(beg = as.Date(beg), end = as.Date(end))
mi <- my.interval("2012-01-01", "2012-12-31")

现在你可以做到:

> as.Date("2012-02-01") %inrange% mi
[1] TRUE

或者定义你自己的inrange - 函数:

my.inrange <- function(x, intv) data.table::inrange(as.Date(x), intv$beg, intv$end)

你可以这样做:

> my.inrange("2012-02-01", mi)
[1] TRUE

正如@Frank评论的那样,您也可以制作my.inrange的中缀变体:

`%my.inrange%` <- my.inrange

现在您也可以使用以下表示法:

"2012-02-01" %my.inrange% mi

类似于data.table betweeninrange函数的中缀表示法。