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

Напомню, что скачать ПО вы можете на сайте SAS, ссылка на документацию по установке SAS UE указана в статье №1.

В данной статье вы познакомитесь с несколькими способами чтения текстовых файлов.



Все примеры основаны на файлах, которые хранятся в директории c:\workshop\habrahabr и были созданы заранее в Notepad.

Для создания набора данных SAS из текстового файла, первый необходимо проанализировать, чтобы верно выбрать тип чтения текстового файла. Текстовый файл может содержать как стандартные, так и не страндартные данные.

Стандартные данные – это данные, которые SAS считает без каких-либо инструкций, например, значение переменной Salary в текстовом файле хранится как 12355.44 или дата уже записана как стандартная дата SAS (см. Урок 1). А если вам необходимо обработать значение, например, $12.355,44 или же 01JAN2018, то требуется указать правило чтения, инструкцию, в соответствии с которой данные значения преобразуются в формат SAS. В данной статье кратко описано применение оператора INPUT для преобразования необработанных данных в наборы данных SAS.

Чтение текстового файла со стандартными данными с разделителем.


Рассмотрим простейший пример текстового файла. Файл managers1.dat является текстовым файлом с разделителем «запятая» и выглядит следующим образом:


Новый набор данных SAS должен содержать следующие переменные: ID, First_Name, Last_Name, Job_Title, Country, Gender, Salary. Вы можете заметить, что данные, хранящиеся в этом файле являются стандартными, и SAS считает их без проблем.

Чтение текстового файла реализуется с помощью операторов INFILE и INPUT на шаге DATA.

Подробно изучить оператор INFILE можно в справочнике SAS 9.4 DATA Step Statements: Reference.

Оператор INFILE задает внешний файл для чтения.

Общий синтаксис оператора:

INFILE file-specification<device-type><options><operating-environment-options>;

file-specification – идентифицирует источник данных, он может быть внешним файлом или ссылкой на внешний файл.
device-type – метод доступа.
options – допустимые опции.
operating-environment-options – параметры рабочей среды.
В нашем конкретном случае оператор INFILE будет записан следующим образом:
infile "c:\workshop\habrahabr\managers1.dat" dlm=',';

DLM= (или delimiter=) — это опция оператора INFILE, которая задает альтернативный разделитель (пробел является разделителем по умолчанию), который будет использован для чтения внешнего файла. Список разделителей указывается в парных кавычках.
После того, как мы задали путь, необходимо задать имена переменных. В решении этой задачи нам поможет оператор INPUT .

Общий синтаксис оператора INPUT:

INPUT <specification(s)> <@ | @@>;

specification(s) – могут включать переменные, списки переменных, признак текстового типа ($), pointer-control, спецификацию столбцов, форматы для чтения и так далее (подробнее – в справочнике SAS 9.4 DATA Step Statements: Reference).

@ — спецификатор удержания строки.

Оператор INPUT в нашем случае будет записан следующим образом:

input ID First_Name $ Last_Name $ Job_Title $ Country $ Gender $ Salary;

Повторюсь еще раз, что чтение текстового файла происходит на шаге DATA, поэтому требуемый для чтения текстового файла код будет выглядеть так:

data managers;
infile "c:\workshop\habrahabr\managers1.dat" dlm=',';
input ID First_Name $ Last_Name $ Job_Title $ Country $ Gender $ Salary;
run;

Мы создаем временный набор данных SAS под названием managers, который будет храниться в библиотеке WORK до закрытия сеанса SAS (см. Урок 2)

Проверим, корректно ли работает код. Запустим программу и проверим Log:


Распечатаем набор данных:

proc print data=managers;
run;

Результат выполнения шага PROC PRINT:


Обратите внимание, что текстовые значения в некоторых столбцах «обрезаны». Запустим процедуру PROC CONTENTS для опеределения длины созданных переменных:

proc contents data=managers varnum;
run;

Опция VARNUM выводит переменные в том порядке, в котором они хранятся в таблице
Фрагмент вывода процедуры:


Длина переменных


По умолчанию SAS Base создает переменные любого типа с длиной 8 байт. Чтобы избежать «обрезанных» значений длину необходимо задавать явно. Данная проблема легко решается с помощью оператора LENGTH.

Важно знать, что данный оператор необходимо писать перед оператором INPUT, это связано с особенностями работы SAS Base.

Итак, наш программный код с использованием оператора LENGTH будет выглядеть следующим образом:

data managers;
infile "c:\workshop\habrahabr\managers1.dat" dlm=',';
length First_Name $ 10 Last_Name $ 12 Job_Title $25 Country $2 Gender $1;
input ID First_Name Last_Name Job_Title Country Gender Salary;
run;

proc print data=managers;
run;
proc contents data=managers varnum;
run;

Принадлежность к типу переменных мы указали в операторе LENGTH, поэтому в INPUT просто перечислили названия переменных. Обратите внимание, что в операторе INPUT переменные перечисляются в том порядке, в каком они располагаются в источнике!

Запустим программу и изучим результаты:

Результат выполнения шага PROC PRINT:


Результат выполнения PROC CONTENTS:


Переменные выведены в другом порядке. Это связано с тем, что SAS Base читает все последовательно: сначала внесены переменные из оператора LENGTH, а лишь потом проверен INPUT, и набор данных дополнен переменными ID и Salary.

Для того, чтобы вывести столбцы в первоначальном порядке, мы можем длину переменных ID и Salary задать явно в операторе LENGTH. Минимальная длина для числовых переменных – 3 байта, но не забывайте, что при изменении длины числовой переменной на меньшую можно потерять точность числовых значений.

Таким образом, программа приобретает следующий вид:

data managers;
infile "c:\workshop\habrahabr\managers1.dat" dlm=',';
length ID 8 First_Name $ 10 Last_Name $ 12 Job_Title $25 Country $2 Gender $1 Salary 8;
input ID First_Name Last_Name Job_Title Country Gender Salary;
run;
proc print data=managers;
run;

Постоянные атрибуты.


На шаге DATA зададим постоянные атрибуты переменным: формат и ярлык. В этом случае атрибуты будут записаны в дескриптор выходного набора данных и будут использоваться на каждом шаге PROC.

data managers;
infile "c:\workshop\habrahabr\managers1.dat" dlm=',';
length ID 8 First_Name $ 10 Last_Name $ 12 Job_Title $25 Country $2 Gender $1 Salary 8;
input ID First_Name Last_Name Job_Title Country Gender Salary;
label 	ID = 'Employee ID'
		First_Name = 'First Name'
		Last_Name = 'Last Name'
		Job_Title = 'Job Title';
format Salary dollar11.2;
run;

proc contents data=managers varnum;
run;

Атрибуты выходного набора данных записаны в дескриптор:



Создадим отчет из полученного набора данных SAS. Обратите внимание, что в опциях PROC PRINT мы указываем параметр label для того, чтобы данная процедура использовала заданные ярлыки в отчете.

proc print data=managers label noobs;
run;


Чтение текстового файла с нестандартными данными с разделителем.


Рассмотрим текстовый файл managers2.dat из директории c:\workshop\habrahabr.

По сравнению с предыдущим есть столбцы, которые содержат не стандартные для SAS данные.


Новый набор данных должен содержать следующие переменные: ID, First_Name, Last_Name, Job_Title, Country, Gender, Salary, Hire_Date.

Переменная Salary содержит специальные символы, также дата в формате SAS — это число, представляющее количество дней, начиная с 1 января 1960 года, (см. Урок 1), а HireDate хранит другие значения. Для того, чтобы считать нестандартные данные необходимо использовать формат ввода – Informat. Важно помнить, что данные в столбце должны быть одного типа для применения формата ввода.

Всю информацию по форматам ввода можно посмотреть в справочнике SAS 9.4 Formats and Informats: Reference.

Infromat – это правило, которое применяется для чтения не стандартных для SAS входных данных. Тип формата для чтения соответствует типу данных SAS. Например, в источнике хранится значение $100,000. Чтобы удалить знак доллара и запятую перед преобразованием данного значения в число, необходимо применить INFORMAT comma8. или dollar8. В этом случае в итоговой таблице будет храниться значения 100000.

Общий синтаксис формата для чтения выглядит следующим образом:

<$>informat<w>.<d>

$ — указатель текстового типа.
Informat — название формата для чтения.
w — ширина поля, включая все символы.
d — количество десятичных знаков.

Считаем текстовый файл managers2.dat

data managers2;
infile "c:\workshop\habrahabr\managers2.dat" dlm=';';
input ID :8. First_Name :$10. Last_Name :$12. Job_Title :$25.
      Country :$2. Gender :$1. Salary :dollar10. Hire_Date :date9.;
label   ID = 'Employee ID'
        First_Name = 'First Name'
        Last_Name = 'Last Name'
        Job_Title = 'Job Title';
format Salary dollar10. Hire_Date date9.;
run;
proc print data=managers2 noobs;
ID ID;
run;

Результаты выполнения процедуры:


Обработка пропущенных значений.


Если в данных есть пропущенные значения, то можно использовать 2 опции DSD и MISSOVER.
DSD ищет пропущенные значение внутри строки, а MISSOVER – в конце.

Таким образом, если мы хотим считать файл managers2a, в котором два подряд идущих разделителя кодируют пропущенное значение:


Используя указанные опции, мы сможем с легкостью считать данный текстовый файл:

data managers2a;
infile "c:\workshop\habrahabr\managers2a.dat" dlm=';' dsd missover;
input ID :8. First_Name :$10. Last_Name :$12. Job_Title :$25.
      Country :$2. Gender :$1. Salary :dollar10. Hire_Date :date9.;
label   ID = 'Employee ID'
        First_Name = 'First Name'
        Last_Name = 'Last Name'
        Job_Title = 'Job Title';
format Salary dollar10. Hire_Date date9.;
run;

proc print data=managers2a;
ID ID;
run;

Результат выполнения программы:


Ошибка чтения данных.


Если в столбце данные разных типов или форматов, рассмотрим следующий пример

В директории c:\workshop\habrahabr хранится файл bad_data.dat


Напишем DATA Step, который считает данный файл:

data new;
infile "c:\workshop\habrahabr\bad_data.dat" dlm=',';
input ID :8. First_Name :$10. Last_Name :$12. Job_Title :$25.
      Country :$2. Gender :$1. Salary :5. Hire_Date :date9.;
label   ID = 'Employee ID'
        First_Name = 'First Name'
        Last_Name = 'Last Name'
        Job_Title = 'Job Title';
format Salary dollar10. Hire_Date date9.;
run;

proc print data=new;
ID ID;
run;

Запустим код и посмотрим Log:

В журнале указание на ошибку чтения данных:


Создаются две автоматические переменные:_N_ и _ERROR_.
_N_ — итерация шага.
_ERROR_ — значение 1 указывает на ошибку.

Результат выполнения программы:


Обратите внимание, что значение «44» в переменной Country считалась без ошибок чтения данных, а для переменных Salary и Hire_Date в Log появилось указание на ошибку чтения данных.

Использование указателя позиции начального символа переменной при чтении текстового файла


Если нам необходимо считать подобный текстовый файл info.dat из директории c:\workshop\habrahabr:


Еще один вариант считать внешний файл – использовать указатель позиции начального символа переменной.

Указывается позиция, имя переменной и формат ввода (informat).

Код для нашего случая будет выглядеть следующим образом:

data info;
infile "c:\workshop\habrahabr\info.dat";
input   @1 ID 3.
        @4 Date mmddyy10.
        @15 Job_Title $11.
        @26 Bonus percent3.;
format Date date9. Bonus percent.;
run;
 proc print data=info;
run;

Запустим код и проверим результат:


Чтение текстового файла с наблюдением в несколько строк.



Если же нам необходимо считать текстовый файл, в котором одно наблюдение занимает несколько строк:


Решить данную задачу можно несколькими способами:

  1. Использовать несколько операторов INPUT.

    data managers6;
    infile "c:\workshop\habrahabr\managers6.dat";
    input ID :8. First_Name :$6. Last_Name :$10.;
    input Job_Title :$11. Country :$2. Gender :$1. Salary :8.;
    run;
    

  2. Использовать указатель.
    SAS загружает следующую запись (строку) при обнаружении символа слэш (/) в операторе INPUT:

    data managers6;
    infile "c:\workshop\habrahabr\managers6.dat";
    input 	ID :8. First_Name :$6. Last_Name :$10./
    		Job_Title :$11. Country :$2. Gender :$1. Salary :8.;
    run;
    


И в том и в другом случае создается набор данных managers6, который находится во временной библиотеке WORK (см. Урок 2)
Распечатаем полученный набор данных:

proc print data=managers6 noobs;
id id;
run;

Результат выполнения процедуры:


Импорт внешних файлов


Для чтения внешних файлов можно использовать процедуру PROC IMPORT.

Импортируем текстовый файл managers5.


Процедура PROC IMPORT в нашем случае выглядит следующим образом:

proc import datafile="C:\workshop\habrahabr\managers5.dat"
            dbms=dlm
            out=managers
            replace;
     delimiter=',';
     getnames=yes;
 run;

proc print data=managers;
run;

Запустим код и посмотрим Log:


Результат выполнения программы:


Итак, это кратко о чтении текстовых файлов. Обратите внимание, что функционал у рассмотренных операторов и процедур намного обширнее, подробное описание представлено в документации.

В следующей статье рассмотрим создание наборов данных SAS. И, конечно, традиционно – Grow with SAS!

Комментарии (0)