SAS 中的 ARRAY 函数在 MEAN 之后(通过分组)

ARRAY function in SAS after MEAN (by grouping)

SAS 有一些作业,但我似乎找不到正确的方法。希望你们中的一些人能够提供帮助。

我们从一个 table 开始,其中我们有以下变量:

City     State     Temp January     Temp Feb     Temp Mar    ...    Temp Dec

首先,我们必须计算平均温度(每月,因此对于 12 个不同的变量)和每个州(因此每个州总是有几个城市)。

我使用了这个代码:

PROC SORT DATA=Homework;
BY state;
RUN;
PROC MEANS DATA=Homework;   
    VAR JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC;
    BY State
    OUTPUT OUT=MTSM (DROP=_type_ _freq_) MEAN=;
    RUN; 

我的结果是 table,其中我有 53 行(每个州一行)和每月 1 列(第一列用于各州)。像这样:

State     JAN       FEB     ...     DEC
State1    xjan      xfeb    ...     xdec
State2                   
...                   
State53                   

现在我需要使用 Array statement 以长格式制作新的 table:

State     Month      Mean_temp
State1    JAN        xjan
state1    FEB        xfeb
.         MAR        ...
.         APR        ...
.         ...        ... 
State1    DEC        xdec
State 2   JAN        ...
          ...
          DEC
...
State53   JAN
          FEB
          ...

有人知道如何做到这一点吗?我完全迷路了。 这是我试过的:

DATA MTSM2;
    SET MTSM;
    BY state;
    ARRAY newvars {1} Mean_Temp;
    ARRAY oldvars {1, 12} JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC;
    DO Month = JAN to DEC;
    DO k=1;
        newvars{k} = oldvars{k, Month};
    END;
    OUTPUT;
    END;
    KEEP state Month Mean_Temp;
RUN;

我收到以下错误:ERROR: Array subscript out of range at line 30 column 22 :'(

我做错了什么?我一直在以多种方式更改它,但总是得到相同的错误。

提前致谢!

听起来您只是想使用 Class 语句而不是 By 语句?

您可以通过在 proc means/proc summary:

中使用更具体的 output 语句来获得您想要的 table
/*Generate some dummy data*/
data have;
call streaminit(1);
do j = 1 to 10;
  do state = 'a', 'b', 'c';
    array months[12] m1-m12;
    do i = 1 to dim(months);
      months[i] = rand('uniform');
    end;
    output;
  end;
end;
drop i j;
run;

proc summary nway data = have;
 var m1-m12;
 class state;
 output out = want(drop = _TYPE_ _FREQ_) mean=;
run;

如果作业是旋转数据,使用 ARRAY,从分类组织布局 (state/month/mean) 到宽布局 ( state/month-1...month-12)可以用BY处理和index判断来填充一个数组。

基本上每个 BY 组将有一行输出。

一种方法是使用 DOW 循环,其中 SET 语句位于显式循环内。

data want(keep=state jan--dec);
  do until (last.state);
    set have;
    by state;
    array months jan feb mar apr may jun jul aug sep oct nov dec;
    index = (index('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC', trim(month))+2)/3;
    months(index) = mean;
  end;
run;

如果已知数据每个月都有,则不需要索引'lookup',直接从do循环索引变量中获取:

data want(keep=state jan--dec);
  do _n_ = 1 by 1 until (last.state);   /* repurpose _n_ */
    set have;
    by state;
    array months jan feb mar apr may jun jul aug sep oct nov dec;
    months(_n_) = mean;
  end;
run;

更新

使用 array 将数据从 across 布局旋转到 down 布局。在数组元素和循环内的 output name/value 对上迭代一个循环。

data want (keep=state month percent);
  set have;
  array months jan feb mar apr may jun jul aug sep oct nov dec;

  do _n_ = 1 to dim(months);
    month = vname(months(_n_));     /* name */
    percent = months(_n_);          /* value */
    OUTPUT;
  end;
run;

Proc TRANSPOSE可以进行相同的数据转换。

当您想同时转置两个或多个数组时,基于数组的旋转非常有用。一个例子是如果你有变量

  • jan_percentdec_percent
  • jan_ratingdec_rating

您想转换成 month/percent/rating 的数据形式。 TRANSPOSE 的这种转换需要多个 proc 步骤(每个数组一个)。

你们很亲近。

没有必要为新变量使用 ARRAY,因为它只是一个。列出实际变量名称后,无需告诉 SAS 数组中有多少个变量。并且数组由整数而不是字符串索引。您可以使用 VNAME() 函数在数组中查找由索引寻址的变量的名称。不需要 BY 语句。

DATA MTSM2;
    SET MTSM;
    ARRAY oldvars JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC;
    length month  mean_temp 8;
    DO month_number = 1 to 12 ;
        month=vname( oldvars[month_number] );
        mean_temp = oldvars[month_number] ;
        OUTPUT;
    END;
    KEEP state Month Mean_Temp;
RUN;