Лекция 2. Программирование на языке SAS. Основы шага DATA (1185374), страница 2
Текст из файла (страница 2)
При вызове функции возвращается значение из начала очереди, далеепроисходит сдвиг и в конец очереди помещается текущее значение аргумента.4. Перед первой итерацией шага DATA очередь заполняется пропущеннымизначениями (missing).13Оператор ARRAYОператор ARRAY — это оператор времени компиляции, которыйопределяет элементы массива. Элементы создаются, если они еще несуществовали в PDV.ARRAY array-name {subscript} <$> <length><array-elements> <(initial-value-list)>;{subscript}Количество элементов.$Обозначает символьные элементы.lengthДлина элементов.array-elementsИмена элементов.array Target{5} (50,100,125,150,200);Массивы (шаг DATA)• Это – удобный способ автоматизировать обработку множества(однотипных) переменных.• Также можно использовать для создания новых переменных.Пример:Есть исходный набор данных с числовыми переменными a1, b2,c3.
Нужно к этим переменным прибавить 1.Создадим «псевдоним с целочисленным индексом» для этихпеременных, и используем цикл для повторяющихся действий.data temp1;array num {*} a1 b2 c3;Входной набор “input”set input;a1b2c3do i=1 to 3;num{i}=num{i}+1;PDVend;run;a1b2c3inum{1} num{2} num{3}«псевдоним» существует только на шаге DATA15Массивы (шаг DATA)Создание массива из новых переменныхdata test;array num11{10};num11{1}=34;num112=12;run;PDVnum111 num112 num113 …. num1110num11{1} num11{2} num11{3} …«псевдоним» существует только на шаге DATAЧисло элементов массива,элементы нумеруются с единицыНачало названия новой переменной – как у массива, азатем идет число. К переменной можно обращаться ипо названию, которое создалось автоматически, ипо псевдониму – названию массива.16Массивы (шаг DATA)• Массивы из символьных переменных.data test;array char{6} $ 20;run;Массив из 6 переменных символьного типа, которые имеют размер 20 байтdata test1;array char{*} $ 20 var22-var33;run;Размер массива может быть опущен (заменён символом «*»), если он ясен «изконтекста», то есть в определении можно понять, для скольких переменныхнужно создать «псевдоним».
В названии переменных для хранения данных, накоторые «ссылается» массив, может быть применён шаблон, который понимаетцелое число в конце названия переменной как счетчик.Переменные могут быть взяты из набора данных, или созданы на шаге DATAdata test2;array char{*} $ 20 aa bb cc;set input;run;17Шаблоны имен переменныхСокращенный способ указания группы имен переменных.Чаще всего используется при обращениях к функциям и процедурам, приопределении массивов, в операторах, работающих со спискомпеременныхSAS допускает использование следующих списков переменных:PDVQtr1 $Qtr2Var1 $Qtr3Qtr4 пронумерованный диапазон: of Qtr1-Qtr4, Var1 не включена диапазон имен в PDV: of Qtr1—Qtr3, Qtr4 не включена, а Var1 включена (PDVможно посмотреть через put _all_) префикс имени: of Qtr:, Var1 не включена специальные списки имен SAS: of _Numerics_, Var1 и Qtr1 не включены18Массивы (шаг DATA)• Врѐменные массивыМассив можно использовать не только для обращения к переменным в PDV и ихсоздания, но и как средство для выделения области памяти, которая неотносится к PDV.data test1;array char{10} $ 20 _temporary_;run;Особенности:1) Обращение к элементам массива – только через название массива и индексэлемента.2) Элементы временного массива RETAIN в отличии от других типов массивов3) В PDV не создаётся никаких переменных для хранения данных.data test1;array char{10} $ 20 _temporary_;put _all_;run;19Нестандартные диапазоны индексов массива• Нестандартные диапазоны задаются через двоеточие:ARRAY name {fromI:toN} …;• Пример расчета и распечатки в журнал числа моделей,сгруппированных по числу цилиндров для набора данных CARS:Переменная спризнаком конца набора• Выход за диапазон – ошибка!• Не всегда удобно пользоваться и часто источник ошибок, лучшеработать со стандартным диапазоном с единицы до N20Использование многомерных массивов• Общий формат многомерного оператора ARRAY это перечислениедипазанов через запятую в скобках:ARRAY array-name {…,rows, cols} <$> <length><elements> <(initial values)>;• Хранится все «последовательно» одним вектором как в C• Например, кодвыдаст в журнал: «В феврале в 1999 28 дней, а в 2000 28 дней»МассивыОсобенности массивов в SAS:• Память для массива выделяется на фазе компиляции шага DATA иосвобождается при его завершении• На шаге DATA нет никаких инструментов для динамического выделенияпамяти (“malloc”) и для её освобождения (“free”), то есть память нельзявыделить позже, чем начнётся шаг DATA, и освободить раньше, чем онзавершится.• Размер массива не может быть динамическим.
Он должен быть известен намомент компиляции шага DATA, но есть функция dim, возвращающаяразмер массива в программу. Зачем?Основные ошибки:• Выход за границы массива (ошибка ловится на этапе выполнения)• Дробный индекс (просто отбрасывается дробная часть индекса), например:data test2;array num1{*} aa bb cc;aa=1; bb=2; cc=3;put num1{1.9}; *в log появится «1».run;• Несогласованность типов (sas попытается сконвертировать без проверок)22Массивы: рецепты• Что можно делать с массивами? (иллюстрации)1) Вычисление функций-«агрегатов» по числовому массивуdata test;a1=1;b2=2;c3=3;d4=4;array eee {4} a1 b2 c3 d4;a=max(of eee[*]);put a=;run;2) Проверка на вхождение значения в массивdata _null_;array list {3} $ 20 ("alpha" "beta" "dima");string="dima";if string in list then put "Ok!";MAX finds maximum value in list.MEDIAN find median of a list of values.CALL MISSING sets all values in as missing.Example: CALL MISSING(OF T(*));CALL SORTN sorts values in the arrayrun;http://support.sas.com/resources/papers/97529_Using_Arrays_in_SAS_Programming.pdfhttp://www.stattutorials.com/SAS/Tutorial-SAS-ARRAYS.html23Массивы: особенности• Обратите внимание, что элементы массива (будучи обычнымипеременными PDV) могут быть сброшены в missing• Если переменная на шаге DATA не была взята из существующего набораданных, то она будет сброшена на последующих итерациях шага DATA.data test;do i=1 to 10;output;end;run;data _null_;set test;array my{3} a b c;if _n_=1 then do;a=1;b=2;c=3;end;i=1 a=1 b=2 c=3 _ERROR_=0 _N_=1i=2 a=.
b=. c=. _ERROR_=0 _N_=2i=3 a=. b=. c=. _ERROR_=0 _N_=3i=4 a=. b=. c=. _ERROR_=0 _N_=4i=5 a=. b=. c=. _ERROR_=0 _N_=5i=6 a=. b=. c=. _ERROR_=0 _N_=6i=7 a=. b=. c=. _ERROR_=0 _N_=7i=8 a=. b=. c=. _ERROR_=0 _N_=8i=9 a=. b=. c=. _ERROR_=0 _N_=9i=10 a=. b=. c=. _ERROR_=0 _N_=10put _all_;run;• Если вы инициализируете массив, то его значения на последующихитерациях сброшены не будут (аналог применения оператора retain).24Создание набора данных• Программно, с помощью оператора datalines шага DATA:data test;length b $ 10;input a b $;datalines;10 test1Создаём переменные в PDV (не обязательно)Оператор input – в какие переменные мы считываемсодержимое неструктурированных данныхПосле datalines идут сами данные (разделитель поумолчанию – пробел.20 test230 test3run;• Программно, с помощью одного или более других наборовданных на шаге DATA• Конкатенация наборов данных (PDV общий, непересекающиесяпеременные заполняются пропусками)• Merge нескольких наборов данных25Импорт данных• А если данные уже лежат в xls, csv? Будем делать так:1.
Загружаем файл вMy Folders любымиспособами, например:2. Code Snippets -> Data -> Import …3. Меняем в программе строчкуDATAFILE="~/имя_файла.xls”4. Меняем название набора данныхOUT=WORK.имя_набора_SAS5. Запускаем.Вместо WORK может быть ваша постояннаябиблиотека.26One-to-One Merge• Нужна сортировка по обoщим уникальным переменнымDATA output_data_set;MERGE input_data_set1 input_data_set2;By variable1 variable2;RUN;• Пример:PerformanceGoalsMonthSalesMonthGoal182231900026034260003422035000DATA compare;MERGE performance goals;BY month;difference=sales-goal;RUN;MonthSalesGoalDifference182239000-77726034600034342205000-780One-to-Many Merge• Тоже нужна сортировка по общим переменным• Если переменные в разных наборах имеют одинаковое имя, тозначение из последнего набора всех «перезапишет»DATA output_data_set;MERGE input_data_set1 input_data_set2;By variable1 variable2;RUN;VideosAdjustmentCategorySalesCategoryAdjustmentAerobics12.99Aerobics.20Aerobics13.99Step.30Aerobics13.99Weights.25Step12.99Step12.99Weights15.99CategorySalesAdjustmentNewPriceAerobics12.99.2010.39DATA prices;Aerobics13.99.2011.19MERGE videos adjustmentAerobics13.99.2011.19Step12.99.309.09Step12.99.309.09Weights15.99.2511.99BY category;NewPrice=(1-adjustment)*sales;RUN;Merge при совпадении и несовпадении• Опция входящего набора данных IN создает переменную, которуюможно использовать для определения соответствий и несоответствий.• Переменная инициализируется нулевым значением, затем ейприсваивается значение 1, если в текущее наблюдение передаютсяданные из набора данных.• Эта программа записывает наблюдения только для соответствий, т.е.аналог SQL Inner join.• Аналогично можно реализовать аналоги SQL left и right outer joinТранспоонирование набора данных• Зачем?• Основная причина – в процессе работы шага DATA мы можемрезультат записывать последовательно в строки, а могутвозникнуть задачи:• Сформировать собственный новый список переменных для наблюденийв новом наборе данных на основе имеющегося• Сгруппировать наблюдения, рассчитать агрегаты и прописать их какновые признаки,• И наоборот, сделать из переменных с результатами агрегации отдельныенаблюдения• Простой пример:• Есть:Надо:30Транспоонирование набора данных на шагеданных• Используемые техники:••••Массивы и циклы для обработки групп переменных внутри наблюденияЯвный OUTPUT для сохранения результатаBY и Fisrt.,Last.