首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R-在多行上将一个间隔分割成多个间隔。

R-在多行上将一个间隔分割成多个间隔。
EN

Stack Overflow用户
提问于 2022-11-10 04:59:39
回答 1查看 44关注 0票数 0

下面的代码生成一个模拟数据集:

代码语言:javascript
复制
library(lubridate)
library(tibble)

example_data = tibble(
  ID = c(1, 2, 3),
  Gender = c("Male", "Female", "Female"),
  Age = c(18, 28, 38),
  Time_Period = c(
    interval(as.Date(now()), as.Date(now() + months(3) + days(10))),
    interval(as.Date(now() + months(1)), as.Date(now() + months(4) + days(13))),
    interval(as.Date(now() + months(2)), as.Date(now() + months(8) + days(4)))
  )
)

具有以下输出

代码语言:javascript
复制
     ID Gender   Age Time_Period                   
  <dbl> <chr>  <dbl> <Interval>                    
1     1 Male      18 2022-11-10 UTC--2023-02-20 UTC
2     2 Female    28 2022-12-10 UTC--2023-03-23 UTC
3     3 Female    38 2023-01-10 UTC--2023-07-14 UTC

每个IDTime_Period变量覆盖一定数量的月。

例如,第一行包含3个月零10天的间隔。对于ID = 1,我希望一个新的数据集包含四行,新的间隔列的长度为一个月,最后一个数据集一直持续到原始间隔的结束点。

这将对所有ID重复。

数据集如下所示,下一行间隔开始日期从上一行开始日期后一个月开始(插入用于可读性的空格):

代码语言:javascript
复制
    ID Gender   Age Split_Up_Intervals                   
 <dbl> <chr>  <dbl> <Interval>                    
     1 Male      18 2022-11-10 UTC--2022-12-09 UTC
     1 Male      18 2022-12-10 UTC--2023-01-09 UTC
     1 Male      18 2023-01-10 UTC--2023-02-09 UTC
     1 Male      18 2023-02-10 UTC--2023-02-20 UTC

     2 Female    28 2022-12-10 UTC--2023-01-09 UTC
     2 Female    28 2023-01-10 UTC--2023-02-09 UTC
     2 Female    28 2023-02-10 UTC--2023-03-09 UTC
     2 Female    28 2023-03-10 UTC--2023-03-23 UTC

     3 Female    38 2023-01-10 UTC--2023-02-09 UTC
     3 Female    38 2023-02-10 UTC--2023-03-09 UTC
     3 Female    38 2023-03-10 UTC--2023-04-09 UTC
     3 Female    38 2023-04-10 UTC--2023-05-09 UTC
     3 Female    38 2023-05-10 UTC--2023-06-09 UTC
     3 Female    38 2023-06-10 UTC--2023-07-09 UTC
     3 Female    38 2023-07-10 UTC--2023-07-14 UTC

我认为这可以使用类似于这里(创建“每天”行,使用tidyverse从选择性的“每月”数字创建)的东西来完成,但我不能完全让它工作。而且,我将使用的实际数据集有大量列,因此我希望在每一行中复制所有其他变量。

EN

回答 1

Stack Overflow用户

发布于 2022-11-10 09:34:59

这是你想做的事情。其思想是,对于每个间隔,我们需要创建一个列,列包含由区间定义的序列(即,如果间隔覆盖4.5个月,则有五个月间隔)。

代码语言:javascript
复制
ex2=data.frame(ID=c(1,2,3), x = c('a','b','c'), n=c(5,6,3))

现在,对于任何特定的行,我们可以使用merge来追加包含可变长度序列的列,让我们使用n列中的值来定义序列的长度:

代码语言:javascript
复制
merge(ex2[1,], 
      data.frame(s=seq(1,ex2[1,]$n)))
代码语言:javascript
复制
  Id x n s
1  1 a 5 1
2  1 a 5 2
3  1 a 5 3
4  1 a 5 4
5  1 a 5 5

现在,以某种方式将其绑定到数据帧的每一行,并绑定输出数据帧。我想你可以用将数据帧的每一行转换为列表做这个,然后用lapply

代码语言:javascript
复制
res=lapply(split(ex2,seq(nrow(ex2))), 
           FUN=function(x) merge(x, data.frame(s=seq(x$n))))
代码语言:javascript
复制
$`1`
  Id x n s
1  1 a 5 1
2  1 a 5 2
3  1 a 5 3
4  1 a 5 4
5  1 a 5 5

$`2`
  Id x n s
1  2 b 6 1
2  2 b 6 2
3  2 b 6 3
4  2 b 6 4
5  2 b 6 5
6  2 b 6 6

$`3`
  Id x n s
1  3 c 3 1
2  3 c 3 2
3  3 c 3 3

现在使用dplyr::bind_rowsdo.call组合数据帧:

代码语言:javascript
复制
library(dplyr)
do.call('bind_rows', res)

我们可以对您的示例数据应用相同的想法。我们不使用n来定义序列的长度,而是创建一个从间隔开始的序列,步骤大小为一个月,其长度是间隔中的月数(或其中的一部分):

代码语言:javascript
复制
do.call("bind_rows", 
        lapply(split(example_data,seq(nrow(example_data))), 
               FUN=function(x) merge(x,  
                      data.frame(start_date=seq(from=int_start(x$Time_Period),
                                                by=duration(1, 'months'),
                                                length.out=ceiling(x$Time_Period/duration(1, 'months')))))))
代码语言:javascript
复制
   ID Gender Age                Time_Period          start_date
1   1   Male  18 2022-11-10 UTC--2023-02-20      UTC 2022-11-10 00:00:00
2   1   Male  18 2022-11-10 UTC--2023-02-20      UTC 2022-12-10 10:30:00
3   1   Male  18 2022-11-10 UTC--2023-02-20      UTC 2023-01-09 21:00:00
4   1   Male  18 2022-11-10 UTC--2023-02-20      UTC 2023-02-09 07:30:00
5   2 Female  28 2022-12-10 UTC--2023-03-23      UTC 2022-12-10 00:00:00
6   2 Female  28 2022-12-10 UTC--2023-03-23      UTC 2023-01-09 10:30:00
7   2 Female  28 2022-12-10 UTC--2023-03-23      UTC 2023-02-08 21:00:00
8   2 Female  28 2022-12-10 UTC--2023-03-23      UTC 2023-03-11 07:30:00
9   3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-01-10 00:00:00
10  3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-02-09 10:30:00
11  3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-03-11 21:00:00
12  3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-04-11 07:30:00
13  3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-05-11 18:00:00
14  3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-06-11 04:30:00
15  3 Female  38 2023-01-10 UTC--2023-07-14      UTC 2023-07-11 15:00:00

我对lubridate还不太了解,不能在这里继续(开始日期不是一个月,您需要正确地设置结束日期,并创建一个间隔),但希望这会有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74384337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档