2016-03-10 7 views
0

Ниже приведен пример того, что я нашел, чтобы изменить данные с длинного на широкий. Но я не могу понять код, особенно то, как они заменяют пробелы и почему. Может кто-нибудь помочь мне понять код?Переформатирование данных от длинного до широкого

Пример 1: Перестройка одна переменная

Начнем с небольшой набор данных только с одной переменной, подлежащей видоизменен. Мы будем использовать переменные year и faminc (для семейного дохода) для создания трех новых переменных: faminc96, faminc97 и faminc98. Во-первых, давайте посмотрим на набор данных и используем proc print для его отображения.

DATA long ; 
    INPUT famid year faminc ; 
CARDS ; 
1 96 40000 
1 97 40500 
1 98 41000 
2 96 45000 
2 97 45400 
2 98 45800 
3 96 75000 
3 97 76000 
3 98 77000 
; 
RUN ; 
PROC PRINT DATA=long ; 
RUN ; 
Obs famid year faminc 

1  1  96  40000 
2  1  97  40500 
3  1  98  41000 
4  2  96  45000 
5  2  97  45400 
6  2  98  45800 
7  3  96  75000 
8  3  97  76000 
9  3  98  77000 

Теперь давайте посмотрим на программу. Первым шагом в процессе преобразования является сортировка данных (с использованием сортировки proc) на идентификационной переменной (famid) и сохранение набора отсортированных данных (longsort). Затем мы пишем шаг данных для фактической перестройки. Мы объясним каждое из утверждений на шаге данных по порядку.

PROC SORT DATA=long OUT=longsort ; 
BY famid ; 
RUN ; 

DATA wide1 ; 
    SET longsort ; 
    BY famid ; 

    KEEP famid faminc96 -faminc98 ; 
    RETAIN faminc96 - faminc98 ; 

    ARRAY afaminc(96:98) faminc96 - faminc98 ; 

    IF first.famid THEN 
    DO; 
    DO i = 96 to 98 ; 
     afaminc(i) = . ; 
    END; 
    END; 

    afaminc(year) = faminc ; 

    IF last.famid THEN OUTPUT ; 

RUN; 
+0

Также вы можете исследовать в качестве альтернативы Proc транспонирования; пример кода proc transpose data = dataset out = reqd_ds; от семьи; год; var faminc; бег; –

ответ

0

Это хороший пример для сравнения и сравнения с DO UNTIL (LAST). Это означает, что RETAIN и INIT отсутствуют на FIRST.FAMID и LAST. Тест на выход OUTPUT. Эти операции выполняются только с использованием встроенных функций цикла шагов данных.

DATA long; 
    INPUT famid year faminc; 
    CARDS; 
1 96 40000 
1 97 40500 
1 98 41000 
2 96 45000 
2 97 45400 
2 98 45800 
3 96 75000 
3 97 76000 
3 98 77000 
;;;; 
    RUN; 
proc print; 
    run; 
data wide; 
    do until(last.famid); 
     set long; 
     by famid; 
     ARRAY afaminc[96:98] faminc96-faminc98; 
     afaminc[year]=faminc; 
     end; 
    drop year faminc; 
    run; 
proc print; 
    run; 
+0

Этот подход называется DO циклом Whitlock (DOW) или Dorfman/Whitlock Loop. Чтобы понять, что происходит, посмотрите на, например, http://support.sas.com/resources/papers/proceedings12/156-2012.pdf – Jetzler

+0

@Jetzler Проверьте это -30 лет. http://www.sascommunity.org/sugi/SUGI83/Sugi-83-171%20Henderson.pdf –

+0

Спасибо за новый способ. Мне просто интересно, следует ли здесь использовать инструкции сохранения и сброса? – user6037890

0

Главный элемент здесь - инструкция сохранения SAS. Datastep выполняется для каждого наблюдения в наборе данных. Для каждой итерации все переменные будут отсутствовать, а затем данные загружаются из набора данных. Если переменная RETAINed, она не будет сброшена, но сохранит информацию с последней итерации.

BY famid ; 

Ваш набор данных упорядочен, а datastep использует оператор by by. Это приведет к инициализации first.famid и last.famid. Это всего лишь двоичные файлы, которые превращаются в 1 для первого/последнего наблюдения одной id-группы.

RETAIN faminc96 - faminc98 ; 

Как уже пояснялось faminc96 - faminc98 сохранит свое значение от одного datastep итерации к следующей.

ARRAY afaminc(96:98) faminc96 - faminc98 ; 

Просто массив, поэтому вы можете вызывать переменные по числу вместо имени.

IF first.famid THEN 
    DO; 
    DO i = 96 to 98 ; 
     afaminc(i) = . ; 
    END; 
    END; 

Для каждого первого наблюдения в группе id сохраняемые переменные сбрасываются. В противном случае вы сохранили бы значения от одной группы od до следующей. То же самое можно сделать с помощью IF first.famid then call missing(of afaminc(*));

afaminc(year) = faminc ; 

Дать информацию в вашем транспонироваться переменными, в зависимости от года.

IF last.famid THEN OUTPUT ; 

После того, как вы написали все значения к новым переменным, вы только ВЫХОДА одно наблюдение (последний) в каждом ид-группы к новому набору данных. Поскольку переменные были сохранены, они все заполнены в этот момент.

Этот быстрый и быстрый сбор данных. Но в целом вы могли бы просто использовать proc transpose

+0

Это помогает мне понять концепцию. Спасибо – user6037890

Смежные вопросы