【问题标题】:Multiple do loops in SASSAS中的多个do循环
【发布时间】:2019-01-29 15:43:26
【问题描述】:

我有一个 2017 年至 2018 年每周收入百分比的数据集。有些人在 2017 年初没有数据,因为他们直到后来才开始赚钱。周数分别为 201701、201702 - 201752 和 201801 - 201852。

我想要做的是有 104 个新变量,称为 WEEK0 - WEEK103,其中 WEEK0 将具有挣钱列的第一个非空列值。以下是数据示例:

MON_EARN_201701      MON_EARN_201702      MON_EARN_201703    MON_EARN_201704
     30                     21                  50                 65   
     .                       .                  30                 100   
     .                      102                 95                 85    

然后我希望我的数据具有以下列(示例)

WEEK0      WEEK1      WEEK2      WEEK3
  30         21         50         65
  30        100          .          .
  102        95         85          .

这些只是一个非常大的数据集的小例子。

我在想我需要尝试做一些 do 循环,所以到目前为止我尝试过的是:

DATA want;
SET have;
ARRAY mon_earn{104} mon_earn_201701 - mon_earn_201752 mon_earn_201801 -mon_earn_201852;
ARRAY WEEK {104} WEEK0 - WEEK103;
DO i = 1 to 104;
IF mon_earn{i} NE . THEN;
WEEK{i} = mon_earn{i};
END;
END;
RUN;

这不起作用,因为当第一个值为空时它不会填充 WEEK0。

如果需要更多信息,请评论,我会添加它。

【问题讨论】:

  • 将您的数据转换为长格式,这将变得非常容易。
  • 如果是长格式怎么办?
  • 你会排序,你可以从第一个不缺失的值开始重新编号。
  • 你能通过回答问题告诉我吗?我不明白如何重新编号整个数据集,因为每一行的第一个非缺失值在不同的一周,我有 100,000 + 行。

标签: sas iteration do-loops


【解决方案1】:

听起来你只需要找到复制的起点。

首先查看按日历月列出的收入列表,直到找到第一个非缺失值。然后将从那里开始的值复制到新的收入数组中(按相对月份)。

data want;
  set have;
  array mon_earn mon_earn_201701 -- mon_earn_201852;
  array week (104);
  do i = 1 to dim(mon_earn) until(found);
    if mon_earn{i} ne . then found=1;
  end;
  do j=1 to dim(week) while (i+j<dim(mon_earn));
    week(j) = mon_earn(i+j-1);
  end;
run;

注意:我简化了 ARRAY 定义。对于输入数组,我假设变量是按顺序定义的,以便您可以使用位置数组列表。对于 WEEK 数组 SAS 和我都喜欢从 1 开始计数,而不是从 0 开始。

【讨论】:

  • 谢谢你的工作。我将能够使用这种方法来解决我遇到的其他问题,再次感谢。
  • 对不起,如果这是一个愚蠢的问题,但我很难完全理解这是如何工作的,你能不能给我发消息解释一下?
  • 什么令人困惑?有两个 ARRAY 语句。在文档中阅读它们是如何工作的。有两个 DO 循环。再次阅读它们是如何工作的。 SAS DO 循环非常强大,因为您可以将迭代循环与 WHILE 或 UNTIL 边界测试结合起来,如本文所述。 TARGET 数组中的索引从 1 开始,当您用完 SOURCE 数组中的条目时停止。
  • FOUND 是一个缺失或为 1 的数字变量。SAS 会将非缺失值和非零值视为 TRUE。所以循环运行直到第一个非缺失值是 FOUND。数组索引是整数。 I、J 和负一是整数。它们的和是另一个整数,用作数组的索引。由于 J 从 1 变为 ...,并且 I 是第一个值的位置,因此 I+J-1 是要复制的当前值的位置。
  • 请注意,您不需要在数据步骤代码中使用新文档用于数组的愚蠢括号 []{}。普通括号工作得很好。我发现他们在代码中产生的视觉差异根本不值得在键盘上找到这些键。
【解决方案2】:

如果是长格式,您可以这样做。长格式时您可能不需要它。

proc sort data=have;
by ID week;
run;

data want;
set have;
by id; *for each group/id counter;
retain counter;
if first.id then counter=0; 
if counter=0 and not missing(value) then do;
counter=1; new_week=0; end;
if counter = 1 then new_week+1;
run;

如果你真的需要它:

  1. 首先找到不缺失的值并将索引存储在 i 中
  2. 从 i 循环到周末维度
  3. 将周分配给从 i 到周结束的 mon_earned。

    data want;
        set have;
        array mon_earned(*) .... ;
        array week(*) ... ;
        found=0; i=0;
    
        do while(found=0);
           if not missing(mon_earned(i)) then found=1;
           i+1;
        end;
    
        z=0;
        do j=i to dim(week);
            week(z) = mon_earned(j); 
            z+1;
        end;
    run;
    

【讨论】:

  • 感谢您的回答。我确实收到错误“错误:数组 mon_earned 在第 343 行第 16 列的第 1 维数组下标 0 超出范围 [1 - 104]”。我假设我需要将变量名输入到数组中,即第一个数组的 mon_earn_201701 - mon_earn_201752 mon_earn_201801 -mon_earn_201852?
【解决方案3】:

您需要第二个索引变量,称为j,以定位正确的星期分配。 j 仅在不缺少一个月收入时才会增加。

此示例代码将“挤出”所有丢失的收入;即使是在一些收入发生之后发生的那些丢失的收入。例如

收入:. . . 10 . 120 . 25 … 会挤到
周:10 120 25 …

data have;
  array earn earn_201701-earn_201752 earn_201801-earn_201852;
  do _n_ = 1 to 1000;
     call missing (of earn(*));
     do _i_ = 1 + 25 * ranuni(123) to dim(earn);
       if ranuni(123) < 0.95 then
         earn(_i_) = round(10 + 125 * ranuni(123));
     end;
     output;
  end;
run;

data want;
  set have;
  array earn earn_201701-earn_201752 earn_201801-earn_201852;
  array week(0:103);

  j = -1;
  do i = 1 to dim(earn);
    if not missing(earn(i)) then do;
      j+1;
      week(j) = earn(i);
    end;
  end;

  drop i j;
run;

如果你想维持内部缺失的收入,逻辑是

    if not missing(earn(i)) or j >=0 then do;
      j+1;
      week(j) = earn(i);
    end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    相关资源
    最近更新 更多