首页 > 解决方案 > R:如何使用其他列中的数据在一列中创建多个新值并为每个新值重复行?

问题描述

我有看起来像这样的数据:

data_t <- data.frame(identfiant = paste0('ID_', 1:5), 
                     date = c('2018-02-06', '2018-05-14', '2018-03-23', '2018-04-10', '2018-03-03'),
                     ndays = c(4,2,3,5,2))

这导致:

    identfiant         date  ndays
1         ID_1   2018-02-06      4
2         ID_2   2018-05-14      2
3         ID_3   2018-03-23      3
4         ID_4   2018-04-10      5
5         ID_5   2018-03-03      2

我想创建一个如下所示的新表:

    identfiant          date  ndays           y
1         ID_1   2018-02-06       4  2018-02-07
2         ID_1   2018-02-06       4  2018-02-08
3         ID_1   2018-02-06       4  2018-02-09
4         ID_1   2018-02-06       4  2018-02-10
5         ID_2   2018-05-14       2  2018-05-15
6         ID_2   2018-05-14       2  2018-05-16
7         ID_3   2018-03-23       3  2018-03-24
8         ID_3   2018-03-23       3  2018-03-25
9         ID_3   2018-03-23       3  2018-03-26
10        ID_4   2018-04-10       5  2018-04-11
11        ID_4   2018-04-10       5  2018-04-12
12        ID_4   2018-04-10       5  2018-04-13
13        ID_4   2018-04-10       5  2018-04-14
14        ID_4   2018-04-10       5  2018-04-15
15        ID_5   2018-03-03       2  2018-03-04
16        ID_5   2018-03-03       2  2018-03-05

如我们所见,每一行初始行都重复ndays了多次,新列y由 组成date + 1:ndays

是否有任何优雅的方法可以使用 dplyr 或 data.table 来做到这一点。我绝对不想使用for循环(对于大量数据来说太长)和seq_along.

我想首先创建一个列,将每一行的所有可能值粘贴在一起,这样我们就可以为第一 y = '2018-02-07;2018-02-08;2018-02-09;2018-02-10' 行创建一个列,然后执行reshape(dcast)or separate_rows。我的代码如下所示:

data_t2 <- data_t %>%
 mutate(
   y = paste0(as.Date(date)+1:ndays, collapse = ";")
 ) %>%
 separate_row(y, sep = ";\\s+")

问题是对于 R 来说,data_t$date是一个向量,并且由于它不会单独处理每一行,因此它会y通过一次处理向量来创建一个新向量data_t$date,并且不知道data_t$ndays要引用哪个值。我们会有向量长度一致性问题。

有人有想法吗?

提前致谢

标签: r

解决方案


我们应该能够在内部dplyrtidyr

使用tidyr::uncount,我们可以根据 复制行来重新格式化数据ndays。接下来,我们将按identfiant(或同时按identfiantdate,取决于是否identfiant不唯一)对数据进行分组。最后,我们将使用mutate来确保我们的date字段属于正确的类,然后在组中添加行号(这将像1:ndays每个组一样。

library(dplyr)
library(tidyr)

data_t %>% 
  uncount(ndays, .remove = FALSE) %>% 
  group_by(identfiant) %>% 
  mutate(date = as.Date(date),
         y = date + row_number())

tidyr接近:

df.expanded <- data_t[rep(seq(nrow(data_t)), data_t$ndays), ]

df.expanded %>% 
  group_by(identfiant) %>% 
  mutate(date = as.Date(date),
         y = date + row_number())

无论哪种方式,这两种方法都为我们提供了以下信息:

# A tibble: 16 x 4
# Groups:   identfiant [5]
   identfiant date       ndays y         
   <fct>      <date>     <dbl> <date>    
 1 ID_1       2018-02-06    4. 2018-02-07
 2 ID_1       2018-02-06    4. 2018-02-08
 3 ID_1       2018-02-06    4. 2018-02-09
 4 ID_1       2018-02-06    4. 2018-02-10
 5 ID_2       2018-05-14    2. 2018-05-15
 6 ID_2       2018-05-14    2. 2018-05-16
 7 ID_3       2018-03-23    3. 2018-03-24
 8 ID_3       2018-03-23    3. 2018-03-25
 9 ID_3       2018-03-23    3. 2018-03-26
10 ID_4       2018-04-10    5. 2018-04-11
11 ID_4       2018-04-10    5. 2018-04-12
12 ID_4       2018-04-10    5. 2018-04-13
13 ID_4       2018-04-10    5. 2018-04-14
14 ID_4       2018-04-10    5. 2018-04-15
15 ID_5       2018-03-03    2. 2018-03-04
16 ID_5       2018-03-03    2. 2018-03-05

推荐阅读