Background

我收到了一个数据帧d:

d <- data.frame(ID = c("a","a","a","a","a","a","a","b","b","c","c"),
                treatment = c(0,1,0,0,0,1,0,1,0,1,1),
                #event = c(0,0,1,1,1,1,1,0,1,1,1),
                service_date = as.Date(c("2011-01-01",   
                                         "2011-08-21",   
                                         "2011-12-23",   
                                         "2012-02-23",   
                                         "2013-09-14",   
                                         "2013-04-07",   
                                         "2014-10-14",   
                                         "2013-01-01",
                                         "2013-12-12",   
                                         "2014-06-17",
                                         "2015-09-29")), 
                stringsAsFactors=FALSE)

> d
   ID treatment service_date
1   a         0   2011-01-01
2   a         1   2011-08-21
3   a         0   2011-12-23
4   a         0   2012-02-23
5   a         0   2013-09-14
6   a         1   2013-04-07
7   a         0   2014-10-14
8   b         1   2013-01-01
9   b         0   2013-12-12
10  c         1   2014-06-17
11  c         1   2015-09-29

它描述了一些人(ID),无论他们是否有treatment,以及每个条目(行)的日期.

The Problem

我想要计算第一行和最后treatment==1行之间的平均持续时间,对于有超过1行的ID,其中treatment==1.

为了更清楚地说明这一点,让我们将这些步骤布置得就像是手动完成的一样,并查看我想要什么答案:

  1. ID号公路a号公路.A先生有7行数据,但只有两行treatment==1:一行是2011-08-21(第二行),另一行是2013-09-14(第六行).如果你手工计算差额,你会发现两者之间有595天.

  2. 对于ID b,我们什么都不做,因为他们只有1treatment==1.(我们将使用filter跳过代码中的b这样的人.)

  3. 对于c先生,我们得到了469天的差额.

  4. 本组平均疗程:(595天+469天)/2人=532 days人.这就是我们想要的结果.

(我完全有可能做错了这个手工计算,这没什么,只要它足以理解我想要做什么即可.如果需要,我很乐意进一步澄清;请让我知道!)

What I've tried

我正在try 修改类似查询中的一些旧代码,以实现以下目的:

d %>%
  group_by(ID) %>%
  filter(sum(treatment) >1) %>%
  mutate(treatment_years = lubridate::time_length(max(service_date) - min(service_date), unit = "year")) %>%
  ungroup() %>%
  summarise(avg = mean(treatment_years),
            sd = sd(treatment_years))

这段代码运行,并将我带到那里.它过滤掉不需要的IDs个,并 for each 人计算一个定义的时间间隔的平均值(和SD).

但这并不完全正确:在lubridate::time_length中,它没有指定条件"最大服务日期where 101"减go "最小服务日期where 101".(粗体部分是缺少的,也是需要的.)

我怎么才能让它做到这一点呢?

我try 过这样的操作,但它只是抛出了一个错误:

d %>%
  group_by(ID) %>%
  filter(sum(treatment) >1) %>%
  mutate(treatment_years = lubridate::time_length(max(service_date) & treatment==1 - min(service_date) & treatment==1, unit = "year")) %>%
  ungroup() %>%
  summarise(avg = mean(treatment_years),
            sd = sd(treatment_years))

推荐答案

我们可以用逻辑向量treatment == 1,即service_date[treatment == 1]来子集service_date(假设存在至少一个‘治疗’级别1)

library(dplyr)
library(lubridate)
d %>%
  group_by(ID) %>%
  filter(sum(treatment) >1) %>%
  summarise(treatment_years = lubridate::time_length(max(service_date[treatment == 1]) - 
                    min(service_date[treatment == 1]), unit = "day"), .groups = 'drop') %>%  
  summarise(avg = mean(treatment_years),
            sd = sd(treatment_years))

-输出

# A tibble: 1 × 2
    avg    sd
  <dbl> <dbl>
1   532  89.1

R相关问答推荐

混淆矩阵,其中每列和等于1

使用R中的gt对R中的html rmarkdown文件进行条件格式设置表的单元格

如何删除多个.CSV文件的行

在(g)子中使用asserable字符

在不安装软件包的情况下测试更新

在数学中正确显示摄氏度、开氏度或华氏度

IMF IFS数据以R表示

使用外部文件分配变量名及其值

如何删除仅在数据集顶部和底部包含零的行

如何使用同比折线图中的个别日

在具有多个响应变量的比例堆叠条形图上方添加总计

如何在GALT包的函数&geom_x样条线中调整线宽

如何移动点以使它们的打印不重叠

如何更改包中函数中的参数?

隐藏基于 case 总数的值

基于R中的引用将向量值替换为数据框列的值

在具有条件的循环中添加行

将`magick`对象转换为原始向量

如何在基数R中根据矩阵散点图中的因子给数据上色?

如何使用包含要子集的值的列表或数据框来子集多个列?