SAS使用数组在事件日期之前选择状态

发布于 2025-02-04 10:05:50 字数 503 浏览 1 评论 0原文

data test;
Input ID $1. Diagnosed_date :ddmmyy10. medication202001 medication202002 
  medication202003 medication202004;
Format diagnosed_date ddmmyy10.;
Datalines;
A 28/02/2020 0 1 1 1
B 28/02/2020 1 1 1 1
C 30/04/2020 0 0 0 1
:
Run;

嗨,我是SAS的新手。以上是临床试验的一个例子。我正在尝试创建一个额外的变量,该变量在诊断为诊断前1个月显示药物状态。因此,例如,对于ID = a,我想将药物状态选择为药物202001,而对于ID = C,用药状态为药物202003。

请注意,该变量的命名惯例具有yyyymm作为后缀。

我的一个朋友建议可以使用SAS数组来完成这项工作,但是我不知道如何创建此功能。我已经尝试过,但根本没有遥不可及。

真的很感谢这里的任何反馈。

data test;
Input ID $1. Diagnosed_date :ddmmyy10. medication202001 medication202002 
  medication202003 medication202004;
Format diagnosed_date ddmmyy10.;
Datalines;
A 28/02/2020 0 1 1 1
B 28/02/2020 1 1 1 1
C 30/04/2020 0 0 0 1
:
Run;

Hi, I’m relatively new to SAS. The above is an example of a clinical trial. I am trying to create an additional variable that shows the medication status 1 month prior to their diagnosed_date. So for example, for ID = A, I want to pick the medication status as medication202001, whereas for ID = C, the medication status as medication202003.

Note the variable’s naming convention has the YYYYMM as the suffix.

A friend of mine has suggested this can be done using SAS array, but I have no idea how to get this created. I’ve tried but didn’t get far at all.

Would really appreciate any feedback here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

木格 2025-02-11 10:05:50

我们可以使用vname()函数循环循环,并读取每个变量名称的一个月部分。我们将从变量的名称中删除所有字母字符,仅留下一个月份。我们可以将其转换为SAS日期。

由于我们知道上个月的时间何时,因此我们只需要将两者进行比较,然后将该变量的值绘制为每行的值即可。当SAS读取202001时,它将自动将其对齐到本月的第一个(例如01JAN2020)。我们将对以前的诊断月进行此操作。

diagnosed_date   last_month   month
28FEB2020        JAN2020      JAN2020 <---- last_month = month. Stop and save the value.
30APR2020        MAR2020      JAN2020
30APR2020        MAR2020      FEB2020
30APR2020        MAR2020      MAR2020 <---- last_month = month. Stop and save the value.

代码:

data want;
    set test;

    array medication_status[*] medication:;

    /* Get the previous month of diagnosed_date and align it to 
       the first day of the month 
    */
    last_month = intnx('month', diagnosed_date, -1, 'B');

    do i = 1 to dim(medication_status);

        /* Get month from var name by removing alphabetic characters 
           and converting to a SAS date 
        */
        month = input(compress(vname(medication_status[i]),,'A'), yymmn6.); 
        
        /* Compare the var's month to the previous month */
        if(month = last_month) then do;
            medication_status_last_month = medication_status[i];

            /* Don't keep checking now that we've found the right date */
            leave;
        end;
    end;

    drop i month last_month;
run;

We can loop through an array and read the month part of each variable name using the vname() function. We'll remove all alphabetic characters from the variable's name, leaving only the month part. We can convert this to a SAS date.

Since we know when the previous month is, we simply need to compare the two together and pull that variable's value for each row. When SAS reads 202001, it will automatically align it to the first of the month (e.g. 01JAN2020). We'll do this to our previous diagnosed_date month.

diagnosed_date   last_month   month
28FEB2020        JAN2020      JAN2020 <---- last_month = month. Stop and save the value.
30APR2020        MAR2020      JAN2020
30APR2020        MAR2020      FEB2020
30APR2020        MAR2020      MAR2020 <---- last_month = month. Stop and save the value.

Code:

data want;
    set test;

    array medication_status[*] medication:;

    /* Get the previous month of diagnosed_date and align it to 
       the first day of the month 
    */
    last_month = intnx('month', diagnosed_date, -1, 'B');

    do i = 1 to dim(medication_status);

        /* Get month from var name by removing alphabetic characters 
           and converting to a SAS date 
        */
        month = input(compress(vname(medication_status[i]),,'A'), yymmn6.); 
        
        /* Compare the var's month to the previous month */
        if(month = last_month) then do;
            medication_status_last_month = medication_status[i];

            /* Don't keep checking now that we've found the right date */
            leave;
        end;
    end;

    drop i month last_month;
run;
柏拉图鍀咏恒 2025-02-11 10:05:50

为此,如果月份连续的月份,则最简单的方法就是基于diagned_date的值直接访问列。但是,这仅有效,如果所有内容都以您可以在列表中使用变量名称的方式对齐或命名。如果它们没有顺序,这将失败,因为您的变量名称不能轻松以单仪表格式列出。

data want;
  set test;
  array medications medication:;
  diag_month = intck('Month','01JAN2020'd,diagnosed_date);  *actually ONE LESS, but that is helpful for us so we leave it;
  if 0 lt diag_month le dim(medications) then 
    medication_status = medications[diag_month];
run;
  

intck中的第一个值是本月的第一天(或任何一天,但我们将在第一个药物列中使用]。 Diag_month是一个偏移量(按设计!)的一个偏移,因为您想要一个偏移 - 如果它使您在技术上是一个偏移的偏移量,那么它是一个偏移,以不同的方式命名,或者将其命名为不同(添加一个)(添加一个),然后稍后减去。

For this, the easiest way to do it if the months are consecutive is to just directly access the column based on the value of the diagnosed_date. This only works, though, if everything is aligned right or named in a way where you can use the variable names in a list. If they're not in order, this will fail since your variable names cannot be easily listed in the single dash format.

data want;
  set test;
  array medications medication:;
  diag_month = intck('Month','01JAN2020'd,diagnosed_date);  *actually ONE LESS, but that is helpful for us so we leave it;
  if 0 lt diag_month le dim(medications) then 
    medication_status = medications[diag_month];
run;
  

The first value in intck is the first day of the month [or any day, but we'll go with first] in the first medication column. The diag_month is one offset (by design!) from its true value, since you want that one offset - if it bothers you that it's technically one off, name it differently or make it not one off (add one) then subtract later.

橘虞初梦 2025-02-11 10:05:50

这是一个不同的答案:我在现实生活中做的方式。

这里的问题是您的数据结构。通常,您不想将数据存储在这样的数组中,而变量的名称意味着某些内容。并不是说这是一件可怕的事情或其他事情,但这只是使它更加工作。很可能数据并不能真正起源 - 即使是那样来的,也可能有人将其转换在某个地方 - 但是即使它这样做也很容易转换,以便它在正确的结构中可以轻松地工作和。

在这里,我们制作一个“药物日期”级别表。然后,加入该表是很微不足道的(要么像我一样使用SQL,要么使用Merge,hash表,或格式或...)以获取您想要的东西 - 而且非常容易调整此。

首先,我们将其转换为垂直药物日期级别表:

data test_vert;
  set test;
  array medications medication:;
  do _i = 1 to dim(medications);
    medicationDate = input(substr(vname(medications[_i]),11,6)||'01',YYMMDD8.);
    medicationValue= medications[_i];
    output;
  end;
  format medicationDate ddmmyy10.;
  keep ID Diagnosed_Date medicationDate medicationValue;
run;

然后,我们进行一个简单的联接以获取所需的值。

proc sql;
  create table want as 
    select test.id, test.diagnosed_date, test_vert.medicationDate, test_vert.medicationValue 
        from test
        left join test_vert
            on test.id=test_vert.id
            and intnx('Month',test.diagnosed_date,-1,'b') = test_vert.medicationDate
    ;
 quit;

Here's a different answer: the way I'd do it in real life.

The issue here is your data structure. You usually don't want to store data in arrays like this where the name of the variable means something. Not that it's a horrible thing to do or anything, but it just makes it a bit more work. Most likely the data doesn't truly originate that way - even if it comes to you that way, someone probably transformed it somewhere - but even if it did, it's very easy to transpose it so that it's in the right structure to easily do work with.

Here, we make a "medication date" level table. Then, it's trivial to join that table (either using SQL as I do, or using a merge, or hash table, or format, or...) to get what you want - and it's very easy to adjust this.

First, we transform it to a vertical medication date level table:

data test_vert;
  set test;
  array medications medication:;
  do _i = 1 to dim(medications);
    medicationDate = input(substr(vname(medications[_i]),11,6)||'01',YYMMDD8.);
    medicationValue= medications[_i];
    output;
  end;
  format medicationDate ddmmyy10.;
  keep ID Diagnosed_Date medicationDate medicationValue;
run;

Then we do a simple join to get the value we want.

proc sql;
  create table want as 
    select test.id, test.diagnosed_date, test_vert.medicationDate, test_vert.medicationValue 
        from test
        left join test_vert
            on test.id=test_vert.id
            and intnx('Month',test.diagnosed_date,-1,'b') = test_vert.medicationDate
    ;
 quit;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文