R: проверить, в каком диапазоне находится дата, имея переменное число диапазонов - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть фрейм данных (dfA), показывающий для каждой страны, когда в первый раз произошел определенный статус c.

Я хотел бы получить фрейм данных (dfGoal), который показывает для каждый день с 1 января 2020 года до сегодняшнего дня, какой статус имел место в этот конкретный c день. В дополнение к этому я также хотел бы видеть с тех пор, когда статус на месте.

Здесь вы можете увидеть минимальный пример моих данных и как мой фрейм данных должен выглядеть в конце.

pacman::p_load(lubridate)

# data frame which shows which status occurred when for the first time
dfA <- data.frame(country = c("Poland", "Poland", "Poland",
                          "Spain", "Spain",
                          "Italy", "Italy", "Italy", "Italy"),
              status = c(0, 1, 2,
                         0, 2,
                         0, 1, 2, 0),
              since = c(20200101, 20200228, 20200312,
                       20200118, 20200301,
                       20200101, 20200212, 20200304, 20200401))

date_seq <- seq(ymd('2020-01-01'),ymd('2020-04-18'), by = '1 day')

# target data frame
dfGoal <- data.frame(curr_date = c(date_seq, date_seq, date_seq),
                 country = c(replicate(109, "Poland"), 
                             replicate(109, "Spain"),
                             replicate(109, "Italy")),
                 status = c(replicate(58, 0),
                            replicate(13, 1),
                            replicate(38, 2),
                            replicate(17, NA),
                            replicate(43, 0),
                            replicate(49, 2),
                            replicate(42, 0),
                            replicate(21, 1),
                            replicate(28, 2),
                            replicate(18, 0)),
                 since = c(replicate(58, 20200101),
                          replicate(13, 20200228),
                          replicate(38, 20200312),
                          replicate(17, NA),
                          replicate(43, 20200118),
                          replicate(49, 20200301),
                          replicate(42, 20200101),
                          replicate(21, 20200212),
                          replicate(28, 20200304),
                          replicate(18, 20200401)))

Я пытался применить предложения, сделанные здесь , но я не смог их решить.

Кто-нибудь знает, как это сделать с помощью dplyr?

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Вот решение с tidyverse, использующее lubridate для преобразования дат из чисел c.

. Вы можете использовать complete для добавления строк дат между 1 января и сегодняшним днем ​​для каждого country, а затем fill status и since столбцов ниже последнего значения.

library(tidyverse)
library(lubridate)

dfA %>%
  mutate(since = ymd(since),
         curr_date = ymd(since)) %>%
  group_by(country) %>%
  complete(curr_date = seq(ymd(20200101), ymd(20200418), by = "1 day")) %>%
  fill(status, since, .direction = "down")

Выход

# A tibble: 327 x 4
# Groups:   country [3]
   country curr_date  status since     
   <fct>   <date>      <dbl> <date>    
 1 Italy   2020-01-01      0 2020-01-01
 2 Italy   2020-01-02      0 2020-01-01
 3 Italy   2020-01-03      0 2020-01-01
 4 Italy   2020-01-04      0 2020-01-01
 5 Italy   2020-01-05      0 2020-01-01
 6 Italy   2020-01-06      0 2020-01-01
 7 Italy   2020-01-07      0 2020-01-01
 8 Italy   2020-01-08      0 2020-01-01
 9 Italy   2020-01-09      0 2020-01-01
10 Italy   2020-01-10      0 2020-01-01
# … with 317 more rows
0 голосов
/ 18 апреля 2020

A data.table решение

library(data.table)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:data.table':
#> 
#>     hour, isoweek, mday, minute, month, quarter, second, wday, week,
#>     yday, year
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union

dfA <- data.frame(country = c("Poland", "Poland", "Poland",
                              "Spain", "Spain",
                              "Italy", "Italy", "Italy", "Italy"),
                  status = c(0, 1, 2,
                             0, 2,
                             0, 1, 2, 0),
                  since = c(20200101, 20200228, 20200312,
                            20200118, 20200301,
                            20200101, 20200212, 20200304, 20200401))
setDT(dfA)


dfA[,since:=ymd(since)]

dfA[,end:={x <- shift(since,-1)
          x <- x-1
                x[is.na(x)] <- ymd(20200418)
                x},by=.(country)]
dfA
#>    country status      since        end
#> 1:  Poland      0 2020-01-01 2020-02-27
#> 2:  Poland      1 2020-02-28 2020-03-11
#> 3:  Poland      2 2020-03-12 2020-04-18
#> 4:   Spain      0 2020-01-18 2020-02-29
#> 5:   Spain      2 2020-03-01 2020-04-18
#> 6:   Italy      0 2020-01-01 2020-02-11
#> 7:   Italy      1 2020-02-12 2020-03-03
#> 8:   Italy      2 2020-03-04 2020-03-31
#> 9:   Italy      0 2020-04-01 2020-04-18


dfA[,.(country=country,status=status,since=since,
       curr_date=seq(from=since,to=end,by="day")),by=1:nrow(dfA)]
#>      nrow country status      since  curr_date
#>   1:    1  Poland      0 2020-01-01 2020-01-01
#>   2:    1  Poland      0 2020-01-01 2020-01-02
#>   3:    1  Poland      0 2020-01-01 2020-01-03
#>   4:    1  Poland      0 2020-01-01 2020-01-04
#>   5:    1  Poland      0 2020-01-01 2020-01-05
#>  ---                                          
#> 306:    9   Italy      0 2020-04-01 2020-04-14
#> 307:    9   Italy      0 2020-04-01 2020-04-15
#> 308:    9   Italy      0 2020-04-01 2020-04-16
#> 309:    9   Italy      0 2020-04-01 2020-04-17
#> 310:    9   Italy      0 2020-04-01 2020-04-18

Создано в 2020-04-19 пакетом Представить (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...