将(先前)强制间隔强制转换为字符串回到间隔

Coercing a (previously) coerced interval into a character string back into an interval

Lubridate 的区间函数及其解析函数允许我们从字符串中获取区间。

# An illustrative example.
my_interval = interval(dmy("15/07/2019"), dmy("15/07/2020"))

打印时,my_interval 如下所示:2019-07-15 UTC--2020-07-15 UTC

现在,完全可以通过as.character函数将一个区间强制转换成一个字符串。然而,反过来呢? 可以将区间强制转换为字符串吗?

也许有人会问为什么我首先要将一个区间强制转换为一个字符串。我实际上有几个间隔,我想通过combn函数获得它们的组合。

# Suppose x is a vector of intervals. Then, what I would like to execute is
combn(x, 2) %>% t() %>% as.data.frame() %>% mutate(overlap = int_overlaps(V1, V2))

但是,当将 combn 应用于区间向量时,出于某种原因,它 returns 是一个数字矩阵。 因此,我认为首先将我的区间向量强制转换为字符向量,然后在获得字符串组合后,将字符串转回区间。

也许如果您通过管道传输一些字符串操作并创建一个用户定义的函数来执行此操作。

library(stringr)
library(lubridate)
library(purrr)

#Example interval:

interval_char<-"2019-07-15 UTC--2020-07-15 UTC"

#transformation
char_to_interval<-function(char){
        char%>%str_split(., " UTC--")%>%
        unlist%>%
        str_remove(.,' UTC')%>%
        map(ymd)%>%
        pmap(.,interval)
}

char_to_interval(interval_char)


[1] 2019-07-15 UTC--2020-07-15 UTC

1) character to interval 如果ch是my_interval的字符表示,那么my_interval2就是从ch重构出来的。我们使用间隔向量 my_intervals 对此进行测试。这也用于其他替代方案。

# test data
my_intervals <- rep(my_intervals, 3)

ch <- format(my_intervals)  # rep)"2019-07-15 UTC--2020-07-15 UTC", 3)

my_intervals2 <- interval(as.Date(ch), as.Date(sub(".*--", "", ch)))

identical(my_intervals, my_intervals2)
## [1] TRUE

2) complex 而不是转换为字符再转换为复数再转换回来。我们使用与上述相同的间隔向量进行测试。

library(zoo)

int2cplx <- function(x) c(cbind(as.Date(int_start(x)), as.Date(int_end(x))) %*% c(1,1i))
cplx2int <- function(x) interval(as.Date(Re(x)), as.Date(Im(x)))

my_intervals2 <- int2cplx(my_intervals)
identical(my_intervals, cplx2int(my_intervals2))
## [1] TRUE

3) combn with indexes 如果在字符和区间之间来回转换的唯一原因是使用 combn,那么使用 combn over indexes。

library(dplyr)
library(lubridate)

# given a 2-vector of indexes, e.g. 1:2, and vector of intervals this returns
#   1 row tibble with cols int1, int2, overlaps of classes interval, interval, logical
ovrlap <- function(index, intervals) {
  ints <- intervals[index]
  tibble(int1 = ints[[1]], int2 = ints[[2]], overlaps = int_overlaps(int1, int2))
} 

my_intervals %>%
  combn(length(.), 2, ovrlap, intervals = ., simplify = FALSE) %>%
  bind_rows

给予:

# A tibble: 3 x 3
  int1                           int2                           overlaps
  <Interval>                     <Interval>                     <lgl>   
1 2019-07-15 UTC--2020-07-15 UTC 2019-07-15 UTC--2020-07-15 UTC TRUE    
2 2019-07-15 UTC--2020-07-15 UTC 2019-07-15 UTC--2020-07-15 UTC TRUE    
3 2019-07-15 UTC--2020-07-15 UTC 2019-07-15 UTC--2020-07-15 UTC TRUE    

4) list comprehension 我们可以使用 listcompr 包来代替使用 combn 来使用 list comprehensions

生成结果
library(lubridate)
library(listcompr)

overlap <- function(x) {
  n <- length(x)
  gen.data.frame(data.frame(int1 = x[i], int2 = x[j], 
    overlaps = int_overlaps(x[i], x[j])), i < j, i = 1:n, j = 1:n)
}

overlap(my_intervals)

给予

                             int1                           int2 overlaps
 1 2019-07-15 UTC--2020-07-15 UTC 2019-07-15 UTC--2020-07-15 UTC     TRUE
 2 2019-07-15 UTC--2020-07-15 UTC 2019-07-15 UTC--2020-07-15 UTC     TRUE
 3 2019-07-15 UTC--2020-07-15 UTC 2019-07-15 UTC--2020-07-15 UTC     TRUE

我已经结合了 GuedesBF 和 G.Grothendieck 慷慨提供的答案的一些方面,以制作矢量化解决方案。

假设 x 是区间向量。然后,我们可以通过执行以下代码得到区间的组合:

combinations = combn(as.character(x), 2) %>% t() %>% as.data.frame()

这里的问题是我们被迫将 x 强制转换为字符向量以便使用 combn 函数。现在我们已经获得了组合,我们需要将我们的数据转回间隔。我们将通过以下功能来做到这一点:

char_2_interval = function(column) { 
     str_split(column, " UTC--", simplify = T) %>% as.data.frame() %>%
     mutate_all(as.Date) %>%
     transmute(interval(V1, V2)) %>% pull()
}

我们将把这个函数应用于组合数据框的所有列。

combinations = combinations %>% mutate_all(char_2_interval)

现在,我们能够辨别出区间对之间的所有重叠,这确实是我从一开始就想做的。

combinations = combinations %>% mutate(overlap = int_overlaps(V1, V2))