Функция ARRAY в SAS после MEAN (путем группировки) - PullRequest
0 голосов
/ 06 ноября 2019

Для SAS есть домашнее задание, и я просто не могу найти правильный способ сделать это. Надеемся, что некоторые из вас смогут помочь.

Мы начнем с таблицы, в которой есть следующие переменные:

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; 

Мой результат - таблица, в которой яиметь 53 строки (по одной на штат) и 1 столбец в месяц (и первый столбец для состояний курсов). Примерно так:

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

Теперь мне нужно использовать Array statement для создания новой таблицы в длинном формате:

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: '(

Что я делаю не так? Я менял это во многих отношениях, но всегда получаюта же ошибка.

Заранее спасибо!

Ответы [ 4 ]

2 голосов
/ 06 ноября 2019

Вы можете получить нужную таблицу, используя более конкретный оператор output в proc means / proc summary:

/*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;
0 голосов
/ 07 ноября 2019

Вы очень близки.

Нет необходимости использовать ARRAY для новой переменной, поскольку она всего одна. Нет необходимости сообщать SAS, сколько переменных в массиве, когда вы перечислили фактические имена переменных. И массивы индексируются целыми числами, а не строками. Вы можете использовать функцию VNAME(), чтобы найти имя переменной, адресуемой индексом, в массив. Оператор BY не нужен.

DATA MTSM2;
    SET MTSM;
    ARRAY oldvars JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC;
    length month $32 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;
0 голосов
/ 06 ноября 2019

Если домашнее задание должно сводить данные, используя 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;

Если известно, что данные имеют каждый месяц, индекс «поиск» не требуется и может быть получен напрямуюиз индексной переменной do loop:

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 для поворота данных из макета через в вниз макет. Выполните итерацию цикла над элементами массива и output парами имя / значение в цикле.

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_percent до dec_percent и
  • jan_rating до dec_rating

, которые вы хотелиповернуть в форму данных month / percent / rating. Такое преобразование с TRANSPOSE требует нескольких шагов процедуры (по одному на массив).

0 голосов
/ 06 ноября 2019

Похоже, вы просто хотите использовать оператор класса вместо оператора By?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...