Saya mencoba mengubah kerangka data df yang terdiri dari kolom value, dua kolom tanggal (start dan end), dan kolom interval (duration) ke dalam format panjang dengan membongkar/membongkar kolom duration.

library(dplyr)
library(lubridate)

df <- data.frame(value = letters[1:3], start = as_date(1:3), end = as_date(3:1)+3) %>% 
          mutate(duration = interval(start, end))

Hasil yang diharapkan adalah kerangka data di mana value, start, dan end diduplikasi untuk setiap hari seperti yang didefinisikan oleh duration. Misalnya, nilai 'a' akan muncul 6 kali setiap kali pada hari yang berbeda (2, 3, 4, 5, 6, 7 Januari 1970).

Saya mencoba menggunakan fungsi unnest dari paket tidyr tetapi tidak ada yang terjadi.

tidyr::unnest(df, duration) 

Setiap bantuan sangat dihargai :)

4
Ben Nutzer 18 Mei 2021, 13:11

6 jawaban

Jawaban Terbaik

Anda tidak dapat membongkar kolom interval dan mengharapkannya menghasilkan semua tanggal di antaranya, tetapi dengan menggunakan seq Anda dapat membuatnya sendiri. Coba ini:

library(tidyverse)
library(lubridate)

df %>%
  rowwise() %>% 
  summarise(
    value, dates = seq(start, end, by = 1)
  )

#> # A tibble: 12 x 2
#>    value dates     
#>    <chr> <date>    
#>  1 a     1970-01-02
#>  2 a     1970-01-03
#>  3 a     1970-01-04
#>  4 a     1970-01-05
#>  5 a     1970-01-06
#>  6 a     1970-01-07
#>  7 b     1970-01-03
#>  8 b     1970-01-04
#>  9 b     1970-01-05
#> 10 b     1970-01-06
#> 11 c     1970-01-04
#> 12 c     1970-01-05

Dibuat pada 2021-05-18 oleh paket repex (v1.0.0)

3
Peter H. 18 Mei 2021, 10:27

Pendekatan data.table

library(data.table)
setDT(df)[, .(date = seq(start, end, by = 1)), by = .(value)]
# value       date
# 1:     a 1970-01-02
# 2:     a 1970-01-03
# 3:     a 1970-01-04
# 4:     a 1970-01-05
# 5:     a 1970-01-06
# 6:     a 1970-01-07
# 7:     b 1970-01-03
# 8:     b 1970-01-04
# 9:     b 1970-01-05
#10:     b 1970-01-06
#11:     c 1970-01-04
#12:     c 1970-01-05
1
Wimpel 18 Mei 2021, 10:58

Dengan uncount

df %>% uncount(as.integer(duration/(24*60*60)) +1) %>%
  group_by(value) %>%
  mutate(date = row_number() -1 + start)

# A tibble: 12 x 5
# Groups:   value [3]
   value start      end        duration                       date      
   <chr> <date>     <date>     <Interval>                     <date>    
 1 a     1970-01-02 1970-01-07 1970-01-02 UTC--1970-01-07 UTC 1970-01-02
 2 a     1970-01-02 1970-01-07 1970-01-02 UTC--1970-01-07 UTC 1970-01-03
 3 a     1970-01-02 1970-01-07 1970-01-02 UTC--1970-01-07 UTC 1970-01-04
 4 a     1970-01-02 1970-01-07 1970-01-02 UTC--1970-01-07 UTC 1970-01-05
 5 a     1970-01-02 1970-01-07 1970-01-02 UTC--1970-01-07 UTC 1970-01-06
 6 a     1970-01-02 1970-01-07 1970-01-02 UTC--1970-01-07 UTC 1970-01-07
 7 b     1970-01-03 1970-01-06 1970-01-03 UTC--1970-01-06 UTC 1970-01-03
 8 b     1970-01-03 1970-01-06 1970-01-03 UTC--1970-01-06 UTC 1970-01-04
 9 b     1970-01-03 1970-01-06 1970-01-03 UTC--1970-01-06 UTC 1970-01-05
10 b     1970-01-03 1970-01-06 1970-01-03 UTC--1970-01-06 UTC 1970-01-06
11 c     1970-01-04 1970-01-05 1970-01-04 UTC--1970-01-05 UTC 1970-01-04
12 c     1970-01-04 1970-01-05 1970-01-04 UTC--1970-01-05 UTC 1970-01-05
2
AnilGoyal 18 Mei 2021, 11:17

Untuk mengekstrak tanggal mulai dan akhir dari interval Anda dapat menggunakan int_start dan int_end, buat urutan tanggal dengan map2 dan unnest.

library(dplyr)
library(purrr)
library(tidyr)
library(lubridate)

df %>%
  mutate(date = map2(int_start(duration), int_end(duration), 
                ~seq(as.Date(.x), as.Date(.y), by = 'day'))) %>%
  #This will also work but would return date of class POSIXct
  #mutate(date = map2(int_start(duration), int_end(duration),seq,by = 'day')) %>%
  unnest(date) %>%
  select(-duration)

#    value start      end        date      
#   <chr> <date>     <date>     <date>    
# 1 a     1970-01-02 1970-01-07 1970-01-02
# 2 a     1970-01-02 1970-01-07 1970-01-03
# 3 a     1970-01-02 1970-01-07 1970-01-04
# 4 a     1970-01-02 1970-01-07 1970-01-05
# 5 a     1970-01-02 1970-01-07 1970-01-06
# 6 a     1970-01-02 1970-01-07 1970-01-07
# 7 b     1970-01-03 1970-01-06 1970-01-03
# 8 b     1970-01-03 1970-01-06 1970-01-04
# 9 b     1970-01-03 1970-01-06 1970-01-05
#10 b     1970-01-03 1970-01-06 1970-01-06
#11 c     1970-01-04 1970-01-05 1970-01-04
#12 c     1970-01-04 1970-01-05 1970-01-05
2
Ronak Shah 18 Mei 2021, 10:20

Anda juga dapat menggunakan solusi berikut. Karena kita akan membuat baris duplikat, kita dapat membungkus operasi dalam daftar dan kemudian menggunakan unnest_longer. purrr fungsi paket selalu menjadi pilihan pertama saya tetapi Anda juga dapat menggunakan ini sebagai alternatif.

library(dplyr)
library(tidyr)
library(lubridate)


df %>% 
  group_by(value) %>%
  mutate(date = list(start + 0:(duration/ddays(1)))) %>%
  unnest_longer(date) %>%
  select(-duration)


# A tibble: 12 x 4
# Groups:   value [3]
   value start      end        date      
   <chr> <date>     <date>     <date>    
 1 a     1970-01-02 1970-01-07 1970-01-02
 2 a     1970-01-02 1970-01-07 1970-01-03
 3 a     1970-01-02 1970-01-07 1970-01-04
 4 a     1970-01-02 1970-01-07 1970-01-05
 5 a     1970-01-02 1970-01-07 1970-01-06
 6 a     1970-01-02 1970-01-07 1970-01-07
 7 b     1970-01-03 1970-01-06 1970-01-03
 8 b     1970-01-03 1970-01-06 1970-01-04
 9 b     1970-01-03 1970-01-06 1970-01-05
10 b     1970-01-03 1970-01-06 1970-01-06
11 c     1970-01-04 1970-01-05 1970-01-04
12 c     1970-01-04 1970-01-05 1970-01-05
3
Anoushiravan R 18 Mei 2021, 11:08

Saya tidak berpikir interval membantu di sini - seq.Date mungkin lebih baik...

library(purrr) #as well as those you have

df <- data.frame(value = letters[1:3], start = as_date(1:3), end = as_date(3:1)+3) %>% 
   mutate(day = map2(start, end, seq.Date, by = "day")) %>% 
   unnest(day)

df
# A tibble: 12 x 4
   value start      end        day       
   <chr> <date>     <date>     <date>    
 1 a     1970-01-02 1970-01-07 1970-01-02
 2 a     1970-01-02 1970-01-07 1970-01-03
 3 a     1970-01-02 1970-01-07 1970-01-04
 4 a     1970-01-02 1970-01-07 1970-01-05
 5 a     1970-01-02 1970-01-07 1970-01-06
 6 a     1970-01-02 1970-01-07 1970-01-07
 7 b     1970-01-03 1970-01-06 1970-01-03
 8 b     1970-01-03 1970-01-06 1970-01-04
 9 b     1970-01-03 1970-01-06 1970-01-05
10 b     1970-01-03 1970-01-06 1970-01-06
11 c     1970-01-04 1970-01-05 1970-01-04
12 c     1970-01-04 1970-01-05 1970-01-05
2
Andrew Gustar 18 Mei 2021, 10:19