2017-12-20 96 views
9

Próbuję znaleźć nakładających się interwałów i postanowiłem dołączyć do siebie dane przedziału z dplyr::left_join(), tak aby móc porównać interwały z lubridate::int_overlaps() do każdego innego interwału przez ten sam identyfikator.Łączenie dwóch ramek danych z przerwami działa niepoprawnie?

Oto, jak się spodziewam, aby zachowywać się left_join(). Dwie tibbles z trzech rzędach tworząc krzyż z 9 rzędów:

library(tidyverse) 

tibble(a = rep("a", 3), b = rep(1, 3)) %>% 
    left_join(tibble(a = rep("a", 3), c = rep(2, 3))) 
Joining, by = "a" 
# A tibble: 9 x 3 
     a  b  c 
    <chr> <dbl> <dbl> 
1  a  1  2 
2  a  1  2 
3  a  1  2 
4  a  1  2 
5  a  1  2 
6  a  1  2 
7  a  1  2 
8  a  1  2 
9  a  1  2 

A oto jak ten sam kod zachowuje się z przerwami. Mam dziewięć rzędów ale wiersze nie krzyżują jak robią powyżej:

tibble(a = rep("a", 3), b = rep(make_date(2001) %--% make_date(2002), 3)) %>% 
    left_join(tibble(a = rep("a", 3), c = rep(make_date(2002) %--% make_date(2003)))) 
Joining, by = "a" 
# A tibble: 9 x 3 
     a        b        c 
    <chr>     <S4: Interval>     <S4: Interval> 
1  a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
2  a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
3  a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
4  a       NA--NA       NA--NA 
5  a       NA--NA       NA--NA 
6  a       NA--NA       NA--NA 
7  a       NA--NA       NA--NA 
8  a       NA--NA       NA--NA 
9  a       NA--NA       NA--NA 

Myślę, że to nieoczekiwane, ale może być czegoś brakuje? Czy to błąd?

Używam 1.7.1, 1.3.4 i 0.7.4.

+0

mogę obejść ten problem przez nie konwersji daty rozpoczęcia i zakończenia do odstępach przed przystąpieniem. – pasipasi

Odpowiedz

4

Wygląda jak błąd w tibble():

> AA <- tibble(a = rep("a", 3), b = rep(make_date(2001) %--% make_date(2002), 3)) 
> class(AA$b) 
[1] "Interval" 
attr(,"package") 
[1] "lubridate" 
> AA 
Error in round_x - lhs : 
    Arithmetic operators undefined for 'Interval' and 'Interval' classes: 
    convert one to numeric or a matching time-span class. 

Jednakże:

> AA <- as.data.frame(AA) 
class(AA$b) 
> class(AA$b) 
[1] "Interval" 
attr(,"package") 
[1] "lubridate" 
> AA 
    a        b 
1 a 2001-01-01 UTC--2002-01-01 UTC 
2 a 2001-01-01 UTC--2002-01-01 UTC 
3 a 2001-01-01 UTC--2002-01-01 UTC 

Dlatego to działa:

> AA <- tibble(a = rep("a", 3), b = rep(make_date(2001) %--% make_date(2002), 3)) 
> BB <- tibble(a = rep("a", 3), c = rep(make_date(2002) %--% make_date(2003))) 
> AA %>% as.data.frame %>% left_join(BB) 
Joining, by = "a" 
    a        b        c 
1 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
2 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
3 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
4 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
5 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
6 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
7 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
8 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
9 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 

choć nie:

> AA %>% left_join(BB) 
Joining, by = "a" 
Error in round_x - lhs : 
    Arithmetic operators undefined for 'Interval' and 'Interval' classes: 
    convert one to numeric or a matching time-span class. 

Uwaga: Używam tibble_1.4.1 (samą wersję lubridate i dplyr jak ty), na badania 3.4.3 dla x86_64-pc-linux-gnu

+1

Interesujące. Dzięki. W tych samych wersjach pakietów co OP, ty na R wersji 3.3.3, otrzymuję identyczne wyjście jako OP, tj. Brak komunikatu o błędzie. Dzięki za twoją pracę. –

7

Bugu

Przedmiotem nadal zawiera istotne informacje:

res <- tibble(a = rep("a", 3), b = rep(make_date(2001) %--% make_date(2002), 3)) %>% 
    left_join(tibble(a = rep("a", 3), c = rep(make_date(2002) %--% make_date(2003)))) 

print.data.frame(res) 
# a        b        c 
# 1 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 2 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 3 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 4 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 5 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 6 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 7 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 8 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 9 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 

res$c  
# [1] 2002-01-01 UTC--2003-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# [5] 2002-01-01 UTC--2003-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# [9] 2002-01-01 UTC--2003-01-01 UTC 

Ale kiedy podzbiorów przez indeksy nie działa anywmore:

res_df <- as.data.frame(res) 

head(res_df) 
    a        b        c 
1 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
2 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
3 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
4 a       NA--NA       NA--NA 
5 a       NA--NA       NA--NA 
6 a       NA--NA       NA--NA 

res_df[4,"c"] 
[1] NA--NA 

i tibble:::print.tbl używają head. Dlatego problem jest natychmiast widoczny z tibbles, a nie z data.frames.

Wpisując str(res$b) widzimy, że mamy tylko 3 start wartości dla 9 data wartości.

jeśli robimy:

[email protected] <- rep([email protected],3) 
[email protected] <- rep([email protected],3) 

eveything teraz drukować prawidłowo:

a        b        c 
1 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
2 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
3 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
4 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
5 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
6 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
7 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
8 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
9 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 

roztworze

Widzieliśmy, że as.data.frame nie wystarczy to, left_join jest funkcja Messing rzeczy w górę, użyj merge zamiast:

res <- tibble(a = rep("a", 3), b = rep(make_date(2001) %--% make_date(2002), 3)) %>% 
    merge(tibble(a = rep("a", 3), c = rep(make_date(2002) %--% make_date(2003))), 
     all.x=TRUE) 

head(res) 
# a        b        c 
# 1 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 2 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 3 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 4 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 5 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 
# 6 a 2001-01-01 UTC--2002-01-01 UTC 2002-01-01 UTC--2003-01-01 UTC 

res[4,"c"] 
#[1] 2002-01-01 UTC--2003-01-01 UTC 

Mam zgłosił problem here

+5

Jest to [problem meta] (https://github.com/tidyverse/dplyr/issues/2432) w celu lepszego wsparcia dla typów innych niż podstawowe w 'dplyr'. I [ten numer] (https://github.com/hadley/vctrs/issues/27) w vctrs. – pasipasi

+0

Dzięki. Istotne jest to, że wygląda na to, że może mieć problemy z 'dplyr :: filter' również w przypadku interwałów lubridate, nadal ze względu na slot' start'. –

Powiązane problemy