Я думаю, что это связано с тем, что на самом деле вычисляет lubridate
.
Когда я вычисляю разницу между date1
и date2
, это происходит:
df %>%
mutate_at(2:3, funs(as.Date(., format = "%Y-%m-%d"))) %>%
mutate(overlap = time2 - time1)
id time1 time2 overlap
1 1 2008-10-12 2009-03-20 159 days
2 1 2008-08-10 2009-06-15 309 days
3 2 2006-01-09 2006-02-13 35 days
4 2 2008-03-13 2008-04-17 35 days
5 3 2008-09-12 2008-10-17 35 days
6 3 2007-05-30 2007-07-04 35 days
7 4 2003-09-29 2004-01-15 108 days
8 4 2003-09-29 2004-01-15 108 days
9 5 2003-04-01 2003-07-04 94 days
10 5 2003-04-01 2003-07-04 94 days
Таким образом, мы можем сказать, что интервалы одинаковы по длине дня.
Теперь, что же на самом деле вычисляет overlap
?Чтобы выяснить, я немного изменил ваш код, чтобы сообщать об опережении и отставании вместо 1.
df %>%
mutate_at(2:3, funs(as.Date(., format = "%Y-%m-%d"))) %>%
mutate(overlap = interval(time1, time2)) %>%
group_by(id) %>%
mutate(cond1 = ifelse(lead(overlap) == overlap, lead(overlap), 0),
cond2 = ifelse(lag(overlap) == overlap, lag(overlap), 0))
# A tibble: 10 x 6
# Groups: id [5]
id time1 time2 overlap cond1 cond2
<int> <date> <date> <S4: Interval> <dbl> <dbl>
1 1 2008-10-12 2009-03-20 2008-10-12 UTC--2009-03-20 UTC 0 NA
2 1 2008-08-10 2009-06-15 2008-08-10 UTC--2009-06-15 UTC NA 0
3 2 2006-01-09 2006-02-13 2006-01-09 UTC--2006-02-13 UTC 3024000 NA
4 2 2008-03-13 2008-04-17 2008-03-13 UTC--2008-04-17 UTC NA 3024000
5 3 2008-09-12 2008-10-17 2008-09-12 UTC--2008-10-17 UTC 3024000 NA
6 3 2007-05-30 2007-07-04 2007-05-30 UTC--2007-07-04 UTC NA 3024000
7 4 2003-09-29 2004-01-15 2003-09-29 UTC--2004-01-15 UTC 9331200 NA
8 4 2003-09-29 2004-01-15 2003-09-29 UTC--2004-01-15 UTC NA 9331200
9 5 2003-04-01 2003-07-04 2003-04-01 UTC--2003-07-04 UTC 8121600 NA
10 5 2003-04-01 2003-07-04 2003-04-01 UTC--2003-07-04 UTC NA 8121600
Здесь мы видим, что lead
и lag
фактически вычисляют различия в конкретном интервале времени, а неглядя на фактические даты начала и окончания интервала.Может показаться, что он видит определенные интервалы как равные, а строки символов - как неравные, какими они и должны быть.
Еще несколько копаний:
Давайте посмотрим на объект, созданный interval
.
a <- interval(df$time1, df$time2)
str(a)
#Formal class 'Interval' [package "lubridate"] with 3 slots
#..@ .Data: num [1:10] 13737600 26697600 3024000 3024000 3024000 ...
#..@ start: POSIXct[1:10], format: "2008-10-12" "2008-08-10" "2006-01-09" ...
#..@ tzone: chr "UTC"
Это класс S4 с тремя слотами: .Data
, start
и tzone
.
Вызов a
показывает нам интервалы.
a
[1] 2008-10-12 UTC--2009-03-20 UTC 2008-08-10 UTC--2009-06-15 UTC 2006-01-09 UTC--2006-02-13 UTC
[4] 2008-03-13 UTC--2008-04-17 UTC 2008-09-12 UTC--2008-10-17 UTC 2007-05-30 UTC--2007-07-04 UTC
[7] 2003-09-29 UTC--2004-01-15 UTC 2003-09-29 UTC--2004-01-15 UTC 2003-04-01 UTC--2003-07-04 UTC
[10] 2003-04-01 UTC--2003-07-04 UTC
Но когда вы выполнили расчет для a
, он выполнил его для .Data
, который представляет собой последовательность секунд, начинающихся с указанной даты (см. ?interval
).
a@.Data
#[1] 13737600 26697600 3024000 3024000 3024000 3024000 9331200 9331200 8121600 8121600
Для начальной даты интервала нам нужно получить доступ к start
слоту.
a@start
#[1] "2008-10-12 UTC" "2008-08-10 UTC" "2006-01-09 UTC" "2008-03-13 UTC" "2008-09-12 UTC"
#[6] "2007-05-30 UTC" "2003-09-29 UTC" "2003-09-29 UTC" "2003-04-01 UTC" "2003-04-01 UTC"
И к часовому поясу ...
a@tzone
#[1] "UTC"
Мы также можем посмотреть на то, чтоотношения между элементами есть.Последний и следующий за последним элементы имели одинаковые интервалы.
a[9] == a[10]
#[1] TRUE
И они являются идентичными объектами.
identical(a[9], a[10])
#[1] TRUE
Но что на самом деле проверяется, когда вы проверяете, является лиэлементы равны?Элементы 3 и 4 имели одинаковую разницу во времени, но не были одинаковыми интервалами.Поэтому, когда вы проверили, были ли их задержки / отведения равными, он вернул TRUE
.Но так как у них разные интервальные даты, они не должны быть.Поэтому, когда мы проверяем, идентичны ли они, только тогда мы получаем то, что ожидали.
a[3] == a[4]
#[1] TRUE
a[3]@.Data == a[4]@.Data
#[1] TRUE
identical(a[3], a[4])
#[1] FALSE
Так что же случилось?Что действительно проверяет a[3] == a[4]
, так это a[3]@.Data == a[4]@.Data
, и поэтому он проверяет, равняется ли 3024000
3024000
.Это так, он возвращает TRUE
.Но идентичные проверяют все слоты и обнаруживают, что они не одинаковы, потому что start
в каждом различны.
Затем я подумал об использовании идентичного с опережением / запаздыванием, чтобы мы могли вписать одну логику в код,но посмотрите на это.
a[9]
#[1] 2003-04-01 UTC--2003-07-04 UTC
# now lead
lead(a[9])
#2003-04-01 UTC--NA
Вывод не выглядит как a[10]
, как ожидалось.
#now lag
lag(a[9])
#[1] NA
#attr(,"start")
#[1] "2003-04-01 UTC"
#attr(,"tzone")
#[1] "UTC"
#attr(,"class")
#[1] "Interval"
#attr(,"class")attr(,"package")
#[1] "lubridate"
Так что lead
и lag
по-разному влияют на класс S4объекты.Чтобы лучше понять, что выводила ваша первая попытка, я сделал следующее:
df %>%
mutate_at(2:3, funs(as.Date(., format = "%Y-%m-%d"))) %>%
mutate(overlap = interval(time1, time2)) %>%
group_by(id) %>%
mutate(cond1 = lead(overlap),
cond2 = lag(overlap))
Я получил много предупреждений, в которых говорилось:
#In mutate_impl(.data, dots) :
# Vectorizing 'Interval' elements may not preserve their attributes
Я не знаю достаточнооб объектах R, чтобы понять, как хранятся данные в классе S4, но, безусловно, выглядит иначе, чем типичный объект S3.
Похоже, использование as.character
, как вы и сделали, - это путь.