【问题标题】:Looping over array, retaining values循环数组,保留值
【发布时间】:2019-09-09 13:39:20
【问题描述】:

我有很多数据集需要具有相同的结构 - 相同的变量、相同的顺序。我有一个用作模板的数据集(下面代码中的“全部”)。通过在同一个 set 语句中列出模板数据集(obs=0)和特定数据集(下面代码中的“some”)来给出其他数据。这工作得很好。

然后我想遍历变量。如果其中一个缺失(如果它不存在于特定数据集中),则应将其设置为前一个变量的值。 var2 应该从 var1 等获取值。 这应该在每一行内完成。如果在单独的数据步骤中完成,这可以正常工作,但如果在上述相同的数据步骤中完成,则不起作用。

如果在同一数据步骤中完成,为缺失值插入的值将始终来自第 1 行。这是为什么呢?我可以在不使用其他数据步骤的情况下获得想要的结果吗?

/*  All the variables a complete data set should contain.*/
data all;
    format var1-var5 $20.;
run;

/*  Actual data have some of these variables, but not all. var1 is never missing, all other variables might be*/
data some;
    var1="Obs 1, Value 1";
    var4="Obs 1, Value 4";
    output;
    var1="Obs 2, Value 1";
    var4="Obs 2, Value 4";
    output;
run;

/*  Not working - The values inserted when the conditional is true are all from row 1*/
data dont_want;
    set all(obs=0) some;
    array chars{*} _character_;
    do i=1 to dim(chars);
        if missing(chars{i}) then chars{i}=chars{i-1};
    end;
    drop i;
run;

/*  Working*/
data temp;
    set all(obs=0) some;
run;

data want;
    set temp;
    array chars{*} _character_;
    do i=1 to dim(chars);
        if missing(chars{i}) then chars{i}=chars{i-1};
    end;
    drop i;
run;

【问题讨论】:

  • DO 循环的下限必须为 2,否则 chars{i-1} 将是无效的数组引用。
  • 是的。但这不会改变所描述的行为。 var1 永远不会丢失,因此 SAS 永远不会尝试检索 chars[0}。
  • @RuneS 仅存在于 ALL (var2 var3 var5) 中的变量不会被重置为丢失。使用 OUTPUT 语句,然后调用 missing(of chars[*])

标签: sas


【解决方案1】:

“额外”变量的值被保留,因为它们来自 ALL 数据集。源自输入数据集的任何变量都不会在数据步迭代开始时重置为缺失。由于这些变量不在某些数据集上,因此在从中读取观察值时它们不会改变。

只需添加代码即可将它们重置为缺失。如果您想在不知道变量名称的情况下执行此操作,您可以考虑重新排序代码。

您可以在编译器“看到”ALL 数据集但运行时读取 SOME 数据集之前定义和清除数组。

data dont_want;
    if 0 then set all;
    array chars{*} _character_;
    call missing(of chars{*});
    set some;
    do i=2 to dim(chars);
        if missing(chars{i}) then chars{i}=chars{i-1};
    end;
    drop i;
run;

或者添加一个显式的 OUTPUT 语句并在之后重置它们。

data dont_want;
    set all(obs=0) some;
    array chars{*} _character_;
    do i=2 to dim(chars);
        if missing(chars{i}) then chars{i}=chars{i-1};
    end;
    drop i;
    output;
    call missing(of _all_);
run;

【讨论】:

    【解决方案2】:

    如果你想使用隐式OUTPUT,需要做几件事

    1. 在读取数据之前准备 PDV set 使用非读取 set
    2. 根据准备好的 PDV 设置阵列
    3. 清空数组
    4. set读取数据
    5. 估算您的数据
    6. 输出

    例子:

    data dont_want;
        if 0 then set all some; * non reading set preps the PDV;
    
        array chars{*} _character_;
    
        call missing(of chars(*)); * clears all auto-retained data set variables;
    
        set all(obs=0) some; * data reading set;
    
        * shift right an array requires left to right processing;
    
        do i=dim(chars) to 2 by -1;
            if missing(chars{i}) then chars{i}=chars{i-1};
        end;
    
        *** OR COPY right into empty slots, repeating prior copy if needed;
    
        do i=2 to dim(chars);
            if missing(chars{i}) then chars{i}=chars{i-1};
        end;
    
        drop i;
    
        * implicit output;
    run;
    

    【讨论】:

      猜你喜欢
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多