R - 从另一个数据框中提取序列的数据框

3

我有一个像这样的数据框:

source_data <-
  data.frame(
    id = c(seq(1,3)),
    start = c(as.Date("2020-04-04"), as.Date("2020-04-02"), as.Date("2020-04-03")),
    end = c(as.Date("2020-04-08"), as.Date("2020-04-05"), as.Date("2020-04-05"))
  )

我想为每个id创建一个日期序列,使其在起始日期和结束日期之间的每一天都被包含,并将其放入另一个数据框中。因此结果应该如下所示:
result <-
  data.frame(
    id = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3),

    date = c(
      as.Date("2020-04-04"),
      as.Date("2020-04-05"),
      as.Date("2020-04-06"),
      as.Date("2020-04-07"),
      as.Date("2020-04-08"),

      as.Date("2020-04-02"),
      as.Date("2020-04-03"),
      as.Date("2020-04-04"),
      as.Date("2020-04-05"),

      as.Date("2020-04-03"),
      as.Date("2020-04-04"),
      as.Date("2020-04-05")
    )
  )

我从这个日期序列开始,但如何将我的source_data数据框加入其中呢?

solution <-
  data.frame(
    date = seq(min(source_data$start), max(source_data$end), by = 1)
  )
3个回答

2
我们可以使用map2来创建每个对应的“开始”和“结束”日期之间的序列,然后展开list列。
library(dplyr)
library(purrr)
library(tidyr)
source_data %>%
    transmute(id, date = map2(start, end, seq, by = '1 day')) %>%
    unnest(c(date))
# A tibble: 12 x 2
#      id date      
#   <int> <date>    
# 1     1 2020-04-04
# 2     1 2020-04-05
# 3     1 2020-04-06
# 4     1 2020-04-07
# 5     1 2020-04-08
# 6     2 2020-04-02
# 7     2 2020-04-03
# 8     2 2020-04-04
# 9     2 2020-04-05
#10     3 2020-04-03
#11     3 2020-04-04
#12     3 2020-04-05

或者使用 data.table

library(data.table)
setDT(source_data)[, .(date = seq(start, end, by = '1 day')), by = id]

base R的附加选项

lst1 <- Map(seq, source_data$start, source_data$end, MoreArgs = list(by = '1 day'))
data.frame(id = rep(source_data$id, lengths(lst1)), date = do.call(c, lst1))

1
聪明的答案玩弄Maplengths!+1 - ThomasIsCoding
我们会为您而战,不用担心。 - utubun
1
我会说你的基础R比我的更简洁,但不知道OP如何决定。 - ThomasIsCoding

2

另一种基于R语言的解决方案

result <- do.call(rbind,
                  c(make.row.names = FALSE,
                    lapply(split(source_data,source_data$id), 
                           function(v) with(v,data.frame(id = id, date = seq(start,end,by = 1))))))

产生
> result
   id       date
1   1 2020-04-04
2   1 2020-04-05
3   1 2020-04-06
4   1 2020-04-07
5   1 2020-04-08
6   2 2020-04-02
7   2 2020-04-03
8   2 2020-04-04
9   2 2020-04-05
10  3 2020-04-03
11  3 2020-04-04
12  3 2020-04-05

1
附加选项。
library(dplyr)
source_data %>% 
  rowwise() %>% 
  mutate(out = list(seq.Date(start, end, "day"))) %>% 
  unnest(out) %>% 
  select(-c(start, end))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接