这是一个tidyverse 解决方案。这个想法是使用tidyr::complete 来生成您想要的全套日期-国家/地区组合。然后很容易使用tidyr::spread 将has_event 的值拆分为每个事件的单独列,并使用sep 参数创建正确的列名称。其余的只是清理 - 将日期转换为单独的 year、month、day 列,删除无关的列,并将事件列中的 NA 替换为 0。这对于更多的国家、每个国家/地区的更多事件或较大的日期范围应该是稳健的。
library(tidyverse)
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
tbl <- read_table2(
"country date1 date2
1 03/01/2012 05/01/2012
2 05/04/2012 12/10/2012
3 07/12/2012 20/03/2012
4 04/02/2012 24/12/2012"
)
#> Warning in rbind(names(probs), probs_f): number of columns of result is not
#> a multiple of vector length (arg 2)
#> Warning: 1 parsing failure.
#> row # A tibble: 1 x 5 col row col expected actual file expected <int> <chr> <chr> <chr> <chr> actual 1 4 date2 "" embedded null literal data file # A tibble: 1 x 5
tbl %>%
gather(event, date, date1:date2) %>%
mutate(date = dmy(date)) %>%
complete(country, date = seq.Date(min(date), max(date), 1)) %>%
mutate(
event = str_remove_all(event, "date"),
has_event = ifelse(is.na(event), 0, 1)
) %>%
spread(event, has_event, sep = "") %>%
mutate_at(vars(event1:event2), replace_na, 0) %>%
mutate(
year = year(date),
month = month(date),
day = day(date)
) %>%
select(country, year:day, event1:event2)
#> # A tibble: 1,428 x 6
#> country year month day event1 event2
#> <int> <dbl> <dbl> <int> <dbl> <dbl>
#> 1 1 2012. 1. 3 1. 0.
#> 2 1 2012. 1. 4 0. 0.
#> 3 1 2012. 1. 5 0. 1.
#> 4 1 2012. 1. 6 0. 0.
#> 5 1 2012. 1. 7 0. 0.
#> 6 1 2012. 1. 8 0. 0.
#> 7 1 2012. 1. 9 0. 0.
#> 8 1 2012. 1. 10 0. 0.
#> 9 1 2012. 1. 11 0. 0.
#> 10 1 2012. 1. 12 0. 0.
#> # ... with 1,418 more rows
由reprex package (v0.2.0) 于 2018 年 3 月 21 日创建。