Выберите предыдущие n переменных для суммирования в SAS - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть несколько файлов данных и итогов в этих файлах данных, которые мне нужно пересчитать.

Переменные разбиты по расе / этнической принадлежности * полу, а затем дается общее количество.

Шаблон повторяется для нескольких тактов, и я не могу реструктурировать файлы данных. Я должен сохранить структуру нетронутой.

ОБНОВЛЕНО: Например, ниже приведены первые 32 переменные (и 10 строк данных) в одном из файлов - латиноамериканские мужчины, латиноамериканские женщины, мужчины американских индейцев, женщины американских индейцев .... всего мужчин и всего женщин для 8 класса, а затем 9 класса.

У меня есть более 100 таких итогов, поэтому я хочу автоматизировать процесс. Как я могу выбрать 7 предыдущих переменных, которые заканчиваются на _M или _F для суммирования (или чего-то такого)? ТИА !!!

G08_HI_M G08_HI_F G08_AM_M G08_AM_F G08_AS_M G08_AS_F G08_HP_M G08_HP_F G08_BL_M G08_BL_F G08_WH_M G08_WH_F G08_TR_M G08_TR_F TOT_G08_M TOT_G08_F G09_HI_M G09_HI_F G09_AM_M G09_AM_F G09_AS_M G09_AS_F G09_HP_M G09_HP_F G09_BL_M G09_BL_F G09_WH_M G09_WH_F G09_TR_M G09_TR_F TOT_G09_M TOT_G09_F 5 2 9 6 2 3 6 9 7 4 1 4 8 4. , 7 11 2 13 4 2 14 10 10 13 2 11 9 5. , 7 1 8 10 2 4 8 0 1 2 8 3 4 5. , 7 13 12 13 5 15 3 2 2 13 11 15 3 15. , 7 8 10 9 0 4 7 9 8 0 3 10 7 1. , 15 9 11 9 11 9 6 7 14 9 12 8 6 14. , 4 8 9 0 10 6 4 3 10 9 2 5 8 2. , 13 2 5 13 3 14 5 15 10 15 7 11 9 6. , 7 6 5 1 4 5 7 4 5 1 8 3 4 4. , 9 7 7 2 4 8 3 4 3 10 9 8 7 7. , 3 1 0 2 4 10 2 10 5 9 7 1 8 8. , 7 9 5 7 13 6 12 13 10 6 2 13 3 12. , 5 7 4 1 7 9 6 8 3 1 3 2 10 4. , 14 12 8 5 6 2 2 5 6 4 12 6 4 5. , 8 9 3 2 3 10 6 5 9 10 8 1 4 5. , 10 2 3 8 3 15 3 14 9 14 3 12 4 12. , 4 3 2 6 4 1 2 5 5 6 4 5 4 1. , 3 14 12 12 15 10 14 11 5 8 9 14 7 15. , 1 10 4 2 1 3 9 8 3 3 3 0 3 1. , 12 9 5 7 14 9 13 9 6 14 5 7 13 13. .

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Это ваши данные? Вы упоминаете, что можете изменить структуру данных, поэтому вам нужно будет «запрограммировать имена переменных», см. Ниже, где у меня есть пример создания массивов (списков переменных), которые группируют имена для G и пола. как подразумевается вашими TOT_: переменными.

data G;
   input G08_HI_M G08_HI_F G08_AM_M G08_AM_F G08_AS_M G08_AS_F G08_HP_M G08_HP_F 
         G08_BL_M G08_BL_F G08_WH_M G08_WH_F G08_TR_M G08_TR_F TOT_G08_M TOT_G08_F 
         G09_HI_M G09_HI_F G09_AM_M G09_AM_F G09_AS_M G09_AS_F G09_HP_M G09_HP_F 
         G09_BL_M G09_BL_F G09_WH_M G09_WH_F G09_TR_M G09_TR_F TOT_G09_M TOT_G09_F;
   cards;
5 2 9 6 2 3 6 9 7 4 1 4 8 4 . . 7 11 2 13 4 2 14 10 10 13 2 11 9 5 . . 
7 1 8 10 2 4 8 0 1 2 8 3 4 5 . . 7 13 12 13 5 15 3 2 2 13 11 15 3 15 . . 
7 8 10 9 0 4 7 9 8 0 3 10 7 1 . . 15 9 11 9 11 9 6 7 14 9 12 8 6 14 . . 
4 8 9 0 10 6 4 3 10 9 2 5 8 2 . . 13 2 5 13 3 14 5 15 10 15 7 11 9 6 . . 
7 6 5 1 4 5 7 4 5 1 8 3 4 4 . . 9 7 7 2 4 8 3 4 3 10 9 8 7 7 . . 
3 1 0 2 4 10 2 10 5 9 7 1 8 8 . . 7 9 5 7 13 6 12 13 10 6 2 13 3 12 . . 
5 7 4 1 7 9 6 8 3 1 3 2 10 4 . . 14 12 8 5 6 2 2 5 6 4 12 6 4 5 . . 
8 9 3 2 3 10 6 5 9 10 8 1 4 5 . . 10 2 3 8 3 15 3 14 9 14 3 12 4 12 . . 
4 3 2 6 4 1 2 5 5 6 4 5 4 1 . . 3 14 12 12 15 10 14 11 5 8 9 14 7 15 . . 
1 10 4 2 1 3 9 8 3 3 3 0 3 1 . . 12 9 5 7 14 9 13 9 6 14 5 7 13 13 . .
;;;;
   run;

Вы можете сделать что-то подобное, чтобы создать массив, который можно использовать в статистических функциях SAS.

proc transpose data=g(obs=0 drop=tot_:) out=gnames;
   var _all_;
   run;
data gnames;
   set gnames;
   g = input(substrn(_name_,2,3),2.);
   length race $2; race=scan(_name_,2,'_');
   length sex  $1; sex =scan(_name_,3,'_');
   run;
proc sort;
   by g sex;
   run;
proc print;
   run;
data _null_;
   set gnames;
   by g sex;
   if first.sex then put +3 'Array G' g z2. sex $1. '[*] ' @;
   put _name_ @;
   if last.sex then put ';';
   run;

405  data _null_;
406     set gnames;
407     by g sex;
408     if first.sex then put +3 'Array G' g z2. sex $1. '[*] ' @;
409     put _name_ @;
410     if last.sex then put ';';
411     run;

   Array G08F[*] G08_HI_F G08_AM_F G08_AS_F G08_HP_F G08_BL_F G08_WH_F G08_TR_F ;
   Array G08M[*] G08_HI_M G08_AM_M G08_AS_M G08_HP_M G08_BL_M G08_WH_M G08_TR_M ;
   Array G09F[*] G09_HI_F G09_AM_F G09_AS_F G09_HP_F G09_BL_F G09_WH_F G09_TR_F ;
   Array G09M[*] G09_HI_M G09_AM_M G09_AS_M G09_HP_M G09_BL_M G09_WH_M G09_TR_M ;
0 голосов
/ 14 сентября 2018

Кажется, что итоговые значения разбиты между переменными, которые должны быть суммированы, поэтому мы можем суммировать "каждую переменную, начиная с последней суммы, которая соответствует некоторым критериям, например, заканчивающаяся на '_F'"?

Это может быть сделано, например, как показано ниже. Я использовал упрощенный набор данных, но итоги - это сумма каждой переменной с момента последнего итога для каждого пола. Я использовал содержание proc, чтобы получить список переменных. Затем я иду по этому списку, выстраивая выражение суммы для мужчин и одно для женщин. Когда встречается переменная с именем tot, законченная строка вида tot1_M = sum (var1_M, var2_M, var3_M); это считается. Эти строки собираются в итоговые значения макропеременных и вставляются в шаг данных.

Если вы знаете, что это всегда 7 переменных для мужчин, 7 женщин и затем сумма, так что вы можете использовать просто положение, а не имя, ниже будет более простое решение.

data old;
    var1_M=1;
    var1_F=2;
    var2_M=3;
    var2_F=4;
    var3_M=5;
    var3_F=6;
    tot1_M=.;
    tot1_F=.;

    var4_M=7;
    var4_F=8;
    var5_M=9;
    var5_F=10;
    var6_M=11;
    var6_F=12;
    tot2_M=.;
    tot2_F=.;
run;

proc contents data=old out=contents noprint;
run;

proc sort data=contents;
    by varnum;
run;

data temp;
    set contents;
    length sumline_F sumline_M $400;
    if _n_=1 then do;
        sumline_M="sum(";
        sumline_F="sum(";
    end;
    retain sumline_M sumline_F;
    if find(name, "_M")>0 and find(name,"tot")=0 then sumline_M=cat(strip(sumline_M),strip(name), ", ");
    else if find(name, "_F")>0 and find(name,"tot")=0 then sumline_F=cat(strip(sumline_F), strip(name), ", ");
    if find(name,"tot")>0 and find(name,"_M")>0 then do;
        sumline_M=substr(sumline_M,1, length(sumline_M)-1); 
        finline=cat(strip(name), "=", strip(sumline_M),");");
        sumline_M="sum(";
    end;
    if find(name,"tot")>0 and find(name,"_F")>0 then do;
        sumline_F=substr(sumline_F,1, length(sumline_F)-1);
        finline=cat(strip(name), "=", strip(sumline_F),");");
        sumline_F="sum(";
    end;
run;

proc sql;
    select finline
    into :totals separated by " "
    from temp
    where not missing(finline);


data new;
    set old;
    &totals;
run;

Если порядок всегда один и тот же (всегда мужской и женский), вы можете сделать так:

/*  Defining data. Note that _M _F are always alternating, with no variables missing*/
data old;
    var1_M=1;
    var1_F=2;
    var2_M=3;
    var2_F=4;
    var3_M=5;
    var3_F=6;
    var4_M=5;
    var4_F=6;
    var5_M=5;
    var5_F=6;
    var6_M=5;
    var6_F=6;
    var7_M=5;
    var7_F=6;
    tot1_M=.;
    tot1_F=.;

    var8_M=7;
    var8_F=8;
    var9_M=9;
    var9_F=10;
    var10_M=11;
    var10_F=12;
    var11_M=11;
    var11_F=12;
    var12_M=11;
    var12_F=12;
    var13_M=11;
    var13_F=12;
    var14_M=11;
    var14_F=12;
    tot2_M=.;
    tot2_F=.;
run;

/*  We have 7 _M and 7 _F-variables, so the first sum variable is number 15, the next 16. Adding 16 gived us the numbers of the next sum-variables*/
data totals;
    do i=15 to 200 by 16;
        output;
    end;
    do i=16 to 200 by 16;
        output;
    end;
run;

/*  Puts the index of the sum variables into a macro variable*/
proc sql;
    select i
    into :sumvars separated by " "
    from totals;

/*  Loop variables using an array. If it is a sum variable, it's the sum of the 7 last variables, skipping every other.*/
data new;
    set old;
    array vars{*} _all_;
    do i=1 to dim(vars);
        if i in (&sumvars) then do;
            vars{i}=sum(vars{i-2}, vars{i-4}, vars{i-6}, vars{i-8}, vars{i-10}, vars{i-12}, vars{i-14});
        end;
    end;
    drop i;
run;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...