【问题标题】:Duration of state in SASSAS 中的状态持续时间
【发布时间】:2015-03-20 11:21:26
【问题描述】:

我有一个关于 SAS 和变量特定状态持续时间分析的问题。我想知道我的数据集中的每个人在状态 b 出现之前持续保持状态 a 的时间。如果状态 c 在状态 a 之后发生,则持续时间应设置为零。请注意,如果 pre_period 处于状态 a,我也会将持续时间设置为零,但如果我之后获得另一个状态 a,则应该计算在内。

数据看起来像这样:

    pre_period    week1 week2 week3 week4 week5 week6 week7 ...
id1 b             b     a     a     a     b     c     c     ...
id2 a             a     a     a     b     a     b     b     ...
id3 b             b     a     a     b     a     a     b     ...
id4 c             c     c     a     a     a     a     a     ...
id5 a             b     a     b     b     a     a     b     ...
id6 b             a     a     a     a     a     a     a     ...

sas代码中的样本集:

data work.sample_data;
input id $ pre_period $  (week1-week7) ($);
datalines;
id1 b b a a a b c c
id2 a a a a b a b b
id3 b b a a b a a b
id4 c c c a a a a a
id5 a b a b b a a b
id6 b a a a a a a a
;

因此,对于 id1,应该给我 3 的持续时间,对于 id2 1,对于 id3 3 和 1,对于 id4 5,对于 id5 1 和 2,对于 id6 7。

所以输出应该看起来像这样:

    dur1 dur2 dur3 dur4 ...
id1 3    .    .    .    ...
id2 1    .    .    .    ...
id3 3    1    .    .    ...
id4 5    .    .    .    ...
id5 1    2    .    .    ...
id6 7    .    .    .    ...

我是 SAS 的初学者,但没有找到解决此问题的方法。请注意,数据集包含几千行和大约一千列,因此对于一个人来说,我可能有几个我都想捕获的状态间隔(因此输出中有几个持续时间变量)。

感谢您的任何建议。谢谢!

【问题讨论】:

  • 您想要的结果似乎与您的要求不一致。状态 c 在第 6 周发生在 id 1 上——这不应该意味着 id 1 的持续时间为 0 吗?而对于 id 2 pre_period 有状态 a,那么 id 2 不应该也有持续时间 0 吗?
  • 也许我有点不清楚:如果 pre_period 是 a 那么下面的 a 不应该被计算在内,但是如果个人离开该州,它应该像其他每个人一样处理。如果 c 在 a 之后,则 c 的情况应该是相关的。感谢您对我的描述的提示!
  • 在多个运行状态 a 由 b 或 c 状态分隔的情况下,您需要什么样的输出并不清楚。您希望每个 id 有 1 行,多列来保存每次运行的长度,还是多行?尝试以与输入数据集相同的格式输入您希望输出数据集的样子。
  • 我编辑了帖子,希望现在更清楚。谢谢!
  • 您应该花一些时间来创建将构建一些示例数据(数据步骤/数据线)的代码。喜欢这个问题stackoverflow.com/q/29152822/2755

标签: sas duration


【解决方案1】:

在这些情况下,明智的做法是根据有限状态机进行思考。这样,如果您的需求发生变化,以后可以很容易地扩展状态机。

持续时间在三种情况下有效(包括从您的结果集中给出的隐含的一种):

  • 状态a 的持续持续时间应该被计算在内,如果
    • 以状态b结束,
    • 数据集结束时仍处于状态a
    • 只要不是在第一周开始,即预期状态为a

首先,我们要处理前期需求,我们可以将这个状态称为pre_period_locked_state

    do week = 1 to last_week;
        if current_state = pre_period_locked_state then do;
            if 'a' not = pre_period or 'a' not = week_state then do;
            current_state = duration_state;
        end;

接下来就是disect是状态不是a的时候,这里叫no_duration_state

        if current_state = no_duration_state then do;
            if 'a' = week_state then do;
                 current_state = duration_state;
            end;
        end;

这是我们的空闲状态,只有在新的持续时间开始时才会改变。下一个状态被命名为duration_state 并定义为:

        if current_state = duration_state then do;
            if 'a' = week_state then do;
                duration_count = duration_count + 1;
            end;
            if ('a' not = week_state or week = last_week) and 0 < duration_count then do;
                current_state = dispatch_state;
             end;
        end;

第一部分可能是自我声明的,持续时间计数器。第二部分负责持续时间结束的时间。

现在转到dispatch_state

        if current_state = dispatch_state then do;
            if 'b' = week_state or 'a' = week_state and week = last_week then do;
                duration{duration_index} = duration_count;
                duration_index = duration_index + 1;
            end;
            duration_count = 0; 
            current_state = no_duration_state;
        end;

这会处理输出表的索引,并确保只存储有效的持续时间。

我在下面添加了id7,因为示例数据没有任何以 b 以外的状态结束的持续时间。

data work.sample_data;
input id $ pre_period $  (week1-week7) ($);
datalines;
id1 b b a a a b c c
id2 a a a a b a b b
id3 b b a a b a a b
id4 c c c a a a a a
id5 a b a b b a a b
id6 b a a a a a a a
id7 b a a c a a a a
;

完整的sas代码状态机:

 data work.duration_fsm;
    set work.sample_data;
    array weeks{*} week1-week7;
    array duration{*} dur1-dur7;

    *states;
    initial_reset_state = 'initial_reset_state';
    pre_period_locked_state = 'pre_period_locked_state';
    duration_state = 'duration_state';
    no_duration_state = 'no_duration_state';
    dispatch_state = 'dispatch_state';
    length current_state $ 50;

    *initial values;
    current_state = initial_reset_state;
    last_week = dim(weeks);

    keep id dur1-dur7;

    do week = 1 to last_week;
        if current_state = initial_reset_state then do;
            duration_count = 0;
            duration_index = 1;
        current_state = pre_period_locked_state;
        end;
        week_state = weeks{week};
        if current_state = pre_period_locked_state then do;
            if 'a' not = pre_period and 'a' = week_state then do;
                    current_state = duration_state;
                end;
            else if 'a' = pre_period and 'a' not = week_state then do;
                current_state = no_duration_state;
            end;
        end;
        if current_state = no_duration_state then do;
            if 'a' = week_state then do;
                 current_state = duration_state;
            end;
        end;
        if current_state = duration_state then do;
            if 'a' = week_state then do;
                duration_count = duration_count + 1;
            end;
            if ('a' not = week_state or week = last_week) and 0 < duration_count then do;
                current_state = dispatch_state;
             end;
        end;
        if current_state = dispatch_state then do;
            if 'b' = week_state or  'a' = week_state and week = last_week then do;
                duration{duration_index} = duration_count;
                duration_index = duration_index + 1;
            end;
            duration_count = 0; 
            current_state = no_duration_state;
        end;
    end;
    run;

这将输出work.duration_fsm:

+-----+------+------+------+------+------+------+------+
| id  | dur1 | dur2 | dur3 | dur4 | dur5 | dur6 | dur7 |
+-----+------+------+------+------+------+------+------+
| id1 |    3 |      |      |      |      |      |      |
| id2 |    1 |      |      |      |      |      |      |
| id3 |    2 |    2 |      |      |      |      |      |
| id4 |    5 |      |      |      |      |      |      |
| id5 |    1 |    2 |      |      |      |      |      |
| id6 |    7 |      |      |      |      |      |      |
| id7 |    4 |      |      |      |      |      |      |
+-----+------+------+------+------+------+------+------+

【讨论】:

    猜你喜欢
    • 2021-12-31
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多