R 中用于计算药物利用率的 SAS 等效代码

问题描述 投票:0回答:1

我有这个数据框的例子。抱歉,我无法分享我的数据集,但它基本上类似于 df。

df <- data.frame(member_id = c(603, 603, 603),
                 fill_dt = c("02/17/2005", "06/13/2005", "08/11/2005"),
                 drug = c("a", "a", "a"),
                 days_supply = c(30,30,30)) # could vary depending on the prescription

我试图找出研究期间(0,180 天)提供药物的天数比例。

第一个期望的输出如下:

这个输出不是问题,我可以使用排列、row_number()、pivot_wider 的组合来实现它。基本上做的就是报纸上做的事情,只不过是在 R 中。他们的开始日是第一次购买处方。由于研究在首次购买后 180 天结束,因此 end_dt = fill_dt1+179。如果有人好奇的话,这是他们之前输出的 SAS 代码:

proc sort data=claims; 
by member_id fill_dt; 
run; 
proc transpose data = claims out=fill_dates (drop=_name_) prefix = fill_dt; 
by member_id; 
var fill_dt; 
run; 
proc transpose data = claims out=days_supply (drop=_name_) prefix = days_supply; 
by member_id; 
var days_supply; 
run; 
data both; 
merge fill_dates days_supply; 
by member_id; 
format start_dt end_dt mmddyy10.; 
start_dt=fill_dt1; 
end_dt=fill_dt1+179; 
run;

这就是事情变得复杂的地方。我想计算 180 天/研究期内单一药物的供应天数。该论文提供了以下 SAS 解决方案:

data pdc; 
set both; 
array daydummy(180) day1-day180; 
array filldates(*) fill_dt1 - fill_dt11; 
array days_supply(*) days_supply1-days_supply11; 
 do ii=1 to 180; daydummy(ii)=0;end; 
 do ii=1 to 180; 
 do i = 1 to dim(filldates) while (filldates(i) ne .); 
 if filldates(i)<= start_dt + ii -1 <= filldates(i)+days_supply(i)-1 
 then daydummy(ii)=1; 
 end; 
 end; 
drop i ii; 
dayscovered=sum(of day1 - day180);label dayscovered='Total Days Covered'; 
p_dayscovered=dayscovered/180;label p_dayscovered='Proportion of Days Covered'; 
run;

基本上,论文会找到该人在哪几天(超过 180 天的时间段)服用药物。提供处方的天数(取决于 days_supply 变量),该天为 1,否则为 0。然后,他们将涵盖的天数 (dayscovered) 相加,并将该变量除以整个研究期间以获得该变量p_dayscovered。预期结果如下:

本文未显示所有列。他们的结果包括全部 180 天。因此,列 day6-day29 实际上不是一列,而是 day6、day7、...、day29,这些列填充了数字 1。 事情实际上变得更加复杂,因为有些处方是重叠的。例如,患者 603 在上一张处方结束前几天购买了新处方。该论文处理重叠的方法是改变新的处方间隔,因为从逻辑上讲,一个人会完成旧的处方以开始新的处方。因此,如果旧处方在 08/05/2005 结束,并且旧处方是在 07/30/2005 购买的,则新处方期限会被推迟,因此实际上会在 08/06/2005 开始。患者可能有多个重叠,因此需要注意这些重叠。事情总是会发生变化,除非处方不重叠。该论文表示,可以在之前的代码中(第二个 DO 之后)使用以下 SAS 代码来实现所需的输出:

 do u=2 to 11 while (filldates(u) ne .); 
 if filldates(u)<filldates(u-1)+days_supply(u-1) 
 then filldates(u)=filldates(u-1)+days_supply(u-1); 
 end;

其图形表示如下所示:

我想这使得 SAS 代码看起来像这样(如果我不明白,请随时纠正我):

data pdc; 
set both; 
array daydummy(180) day1-day180; 
array filldates(*) fill_dt1 - fill_dt11; 
array days_supply(*) days_supply1-days_supply11; 
 do ii=1 to 180; daydummy(ii)=0;end; 
 do ii=1 to 180; 
 do i = 1 to dim(filldates) while (filldates(i) ne .); 
 if filldates(i)<= start_dt + ii -1 <= filldates(i)+days_supply(i)-1 
 then daydummy(ii)=1; end;
do u=2 to 11 while (filldates(u) ne .); 
 if filldates(u)<filldates(u-1)+days_supply(u-1) 
 then filldates(u)=filldates(u-1)+days_supply(u-1); 
 end;  
 end; 
drop i ii; 
dayscovered=sum(of day1 - day180);label dayscovered='Total Days Covered'; 
p_dayscovered=dayscovered/180;label p_dayscovered='Proportion of Days Covered'; 
run;

我想知道是否可以使用 R(第二、第三和第四个 SAS 代码块)来完成所有这些操作。第一部分已得到处理。但我在计算天数列和重叠方面惨遭失败。有问题的论文是:https://support.sas.com/resources/papers/proceedings/proceedings/forum2007/043-2007.pdf

编辑:我有兴趣将这一时期的每一天保留为一列,就像提供的照片和文章中一样(填写处方的日期为 1,否则为 0)。这样我就可以计算出一个人每周接触药物的天数。这就是为什么转移重叠的日子也很重要,因为我能够跟踪这些日子。

r sas
1个回答
2
投票

好吧,我想当你第一次提出这个问题时我知道你想做什么。

首先,最好的(我认为)库是

tidyverse
lubridate
。我首先添加更多行是为了提供更多视图。

structure(list(member_id = c(603, 603, 603, 604, 604), fill_dt = c("02/17/2005", 
"06/13/2005", "08/11/2005", "06/15/2005", "08/13/2005"), drug = c("a", 
"a", "a", "a", "a"), days_supply = c(30, 30, 30, 60, 30)), class = "data.frame", row.names = c(NA, 
-5L))

df1 <- df %>% 
       mutate(fill_dt = as.Date(fill_dt, format = "%m/%d/%y")) %>% 
       group_by(member_id, drug) %>% 
       filter(row_number() == 1) %>% 
       mutate(study_end = fill_dt + days(180)) %>% 
       transmute( days_range = map2(fill_dt, study_end, seq, by = "1 day")) %>% 
       unnest(days_range)

您的数据应如下所示:

# A tibble: 362 x 3
# Groups:   member_id, drug [2]
   member_id drug  days_range
       <dbl> <chr> <date>    
 1       603 a     2020-02-17
 2       603 a     2020-02-18
 3       603 a     2020-02-19
 4       603 a     2020-02-20
 5       603 a     2020-02-21
 6       603 a     2020-02-22
 7       603 a     2020-02-23
 8       603 a     2020-02-24
 9       603 a     2020-02-25
10       603 a     2020-02-26
# i 352 more rows

第一部分从长远角度获取您的数据。如前所述,SAS 和 R 之间的区别是 SAS 是基于行的,而 R 是基于列的。这就是为什么以这种方式构建数据很重要。

然后我们需要通过

summarise
member_id
创建标志和
drug
数据。

df_fin <- df1 %>% 
          left_join(df %>% 
                    mutate(fill_dt = as.Date(fill_dt, format = "%m/%d/%y"), 
                           fill_dt_end = fill_dt + days(days_supply)) %>% 
                    group_by(member_id, drug), by = c("member_id", "drug") , 
                    relationship = "many-to-many") %>% 
          mutate(covered_flg = if_else(days_range %within% interval(fill_dt, fill_dt_end), 1, 0)) %>% 
          group_by(member_id, drug, days_range) %>% 
          summarise(covered_flg = max(covered_flg)) %>% 
          ungroup(days_range) %>% 
          summarise(covered_days = sum(covered_flg)) %>% 
          ungroup() %>% mutate(prop_days_covered = covered_days/180)

上面的代码首先通过

df1
left_joins
建立多对多关系中的
member_id
drug
的开始日期 (
fill_dt
) 和结束日期 (
fill_dt_end
=
fill_dt + days supply
)处方配齐。根据日期范围,如果长格式的日期(来自
df1
)在
fill_dt
fill_dt_end
之间的范围内,此代码将创建一个标志。然后由于多对多连接,我们得到
max

这应该产生

df_fin

# A tibble: 2 x 4
  member_id drug  covered_days prop_days_covered
      <dbl> <chr>        <dbl>             <dbl>
1       603 a               67             0.372
2       604 a               90             0.5 
© www.soinside.com 2019 - 2024. All rights reserved.