Чтение файла Excel в sas с столбцами даты - PullRequest
0 голосов
/ 17 июня 2020

Я столкнулся с проблемой при импорте файла Excel в среду sas. Итак, в основном в файле Excel есть несколько столбцов с именами

Geography   
AR_NO   
31-Jan-18   
28-Feb-18   
31-Mar-18   
30-Apr-18   
31-May-18   
30-Jun-18

После использования кода ниже ->

%macro FX_Lkup(sheet);
FILENAME FXFILE "/idn/home/Module2/excel.xlsx";

PROC IMPORT DATAFILE=FXFILE
       DBMS=XLSX
       OUT=&sheet. 
       REPLACE
       ;
       SHEET="&sheet."; 
       RUN;

%mend FX_Lkup;
%FX_Lkup(LENDING_TEMPLATE);
%FX_Lkup(2018FXRates);

SAS data print the columns as 
    Geography   
    AR_NO   
    43131
    43159
    43190
    43220
and so on.

Есть ли решение по этому поводу? Мы будем очень благодарны за любую инициативу :)

Спасибо!

Ответы [ 3 ]

1 голос
/ 17 июня 2020

Он импортирован правильно, SAS использует числа для хранения дат. чтобы указать дату в итоговой таблице, необходимо указать format = AFRDFDE7., например

0 голосов
/ 17 июня 2020

IMPORT использует заголовки столбцов с оценкой даты Excel в качестве чисел дат эпохи Excel.

Используйте Proc DATASETS, чтобы изменить метку столбца и, возможно, переименовать столбцы во что-то общее c, например DATE1-DATE6. Или продолжите и затем разверните данные в категориальную форму со столбцами GEO, AR_NO, DATE, VALUE

Вы можете спросить себя «Откуда эти числа , например, 43131, откуда? " или " Что такое номер даты эпохи Excel? "

Это неформатированные значения даты Excel. Считываемая человеком дата, представленная числом, определяется системой эпоха или датой, представленной числом 0.

Различные системы отсчета времени имеют разные эпохи (начальные точки) и единицы времени. Некоторые примеры:

  • 21DEC1899 Дата и время в Excel 0, 1 = 1 день
  • 01JAN1960 Дата SAS номер 0, 1 = 1 день
  • 01JAN1960 SAS datetime number 0, 1 = 1 секунда
  • 01JAN1970 Unix OS datetime number 0, 1 = 1 секунда

Чтобы преобразовать номер даты Excel в дату SAS число, которое вам нужно вычесть 21916, то есть количество дней от 31DEC1899 до 01JAN1960

Это понимание даты эпох будет использоваться при установке метки столбца SAS и переименование столбца.

Для других возни с кодом, следующее создаст рабочий лист Excel с заголовками столбцов с оценкой даты . Я предполагаю, что такая ситуация может иначе возникнуть при импорте рабочего листа, содержащего сводную таблицу Excel .

Сначала создайте образец данных SAS

data demo_tall;
  do Geography = 'Mountains', 'Plains';
  do AR_NO = 1 to 3;
    _n_ = 0;
    length label $200;
    do label = '31-Jan-18', '28-Feb-18', '31-Mar-18',
               '30-Apr-18', '31-May-18', '30-Jun-18'
    ;
        _n_ + 1;
        name = cats('Date',_n_);
        value + 1;
        output;
    end;
  end;
  end;
run;

proc transpose data=demo_tall out=demo_wide(drop=_name_);
  by Geography AR_NO;
  var value;
  id name;
  idlabel label;
run;

Образец набора данных SAS ( с поворотом с транспонированием) enter image description here

Затем создайте лист Excel с датой Excel и отформатированными заголовками столбцов

ods noresults;
ods excel file='%TEMP%\across.xlsx' options(sheet_name='Sample');

data _null_;
  declare odsout xl();

  if 0 then set demo_wide;
  length _name_ $32;

  xl.table_start();
    * header;
    xl.row_start();
      do _n_ = 1 to 100; * 100 column guard;
        call vnext(_name_);
        if _name_ = '_name_' then leave;

        _label_ = vlabelx(_name_);
        _date_ = input(_label_, ?? date9.);

        * make some header cells an Excel date formatted value;

        if missing(_date_) then
          xl.format_cell(data:_label_);
        else
          xl.format_cell(
            data:_date_,
            style_attr:"width=9em tagattr='type:DateTime format:dd-mmm-yy'"
          );
      end;
    xl.row_end();

    * data rows;
    do _n_ = 1 by 1 while (not lastrow);
      set demo_wide end=lastrow;

      xl.row_start();
        call missing(_name_);
        do _index_ = 1 to 100; * 100 column guard;
          call vnext(_name_);
          if _name_ = '_name_' then leave;

          xl.format_cell(data:vvaluex(_name_));
        end;
      xl.row_end();
    end;

  xl.table_end();

  stop;
run;

ods excel close;
ods results;

Создан файл Excel
enter image description here

ИМПОРТ листа Excel

Журнал покажет «забавность» заголовков столбцов с датой

options msglevel=I;

proc import datafile='%temp%\across.xlsx' dbms=xlsx replace out=want;
  sheet = "Sample";
run;

proc contents noprint data=want out=want_meta(keep=name label varnum);
run;
----- LOG -----
1380  proc import datafile='%temp%\across.xlsx' dbms=xlsx replace out=want;
1381    sheet = "Sample";
1382  run;

NOTE:    Variable Name Change.  43131 -> _43131
NOTE:    Variable Name Change.  43159 -> _43159
NOTE:    Variable Name Change.  43190 -> _43190
NOTE:    Variable Name Change.  43220 -> _43220
NOTE:    Variable Name Change.  43251 -> _43251
NOTE:    Variable Name Change.  43281 -> _43281
NOTE: VARCHAR data type is not supported by the V9 engine. Variable Geography has been converted
      to CHAR data type.
NOTE: The import data set has 6 observations and 8 variables.
NOTE: WORK.WANT data set was successfully created.
NOTE: PROCEDURE IMPORT used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds

Изменить заголовок (метаданные) импортированного набора данных

Имена столбцов со значением даты будут переименованы в DATE1-DATE6, а метка будет изменена на соответствующую дату в формате SAS DATE11. (dd-mon-yyyy)


%let renames=;
%let labels=;

data _null_;
  length newname $32;
  length renames labels $32767;
  retain renames labels;

  set meta end=lastvar;

  date = coalesce(input(label, ?? 5.),1e9) + '31dec1899'd;


  if '01jan1980'd < date < today() then do;
    index + 1;

    newname = cats('DATE',index);
    label = quote(trim(put(date,date11.)));

    labels  = catx(' ', labels,  catx('=',name,label));
    renames = catx(' ', renames, catx('=',name,newname));
  end;

  if lastvar;

  if not missing(labels)  then call symput('labels',  trim('LABEL '  || labels));
  if not missing(renames) then call symput('renames', trim('RENAME ' || renames));
run;

proc datasets nolist lib=work;
  modify want;
  &labels;
  &renames;
run;
quit;

%symdel labels renames;

%let syslast = want;

Результат при печати. ​​

enter image description here enter image description here

Необязательно

Преобразование в категориальную форму (вертикальный макет)

proc transpose data=want out=stage1(rename=(col1=value _label_=date_string));
  by geography ar_no;
  var date:;
  label _name_ = ' ';
  label date_string = ' ';
run;

data want_tall;
  set stage1;
  date = input (date_string, date11.);
  format date date11.;
  keep geography ar_no _name_ date value;
run;
0 голосов
/ 17 июня 2020

Если у вас есть смешанные символьные и числовые c значения в одном столбце, тогда SAS будет вынужден создать переменную как символьную. Когда он это делает, он сохраняет число, которое Excel использует для даты, в виде строки цифр. Чтобы преобразовать его в дату в SAS, сначала преобразуйте строку цифр в число, а затем отрегулируйте число, чтобы учесть разницу в том, как SAS и Excel считают дни.

data want ;
  set LENDING_TEMPLATE ;
  date = input(geography,??32.) + '30DEC1899'd;
  format date date9.;
run;

Даты как заголовки

Если ваш файл Excel использует даты в качестве заголовков столбцов, SAS также преобразует их в строки di git, поскольку имена переменных всегда являются строками символов, а не числами. Один из быстрых способов исправить это - использовать PRO C TRANSPOSE. Это будет легко, если каждая строка однозначно идентифицируется другими переменными и когда все переменные «даты» имеют числовое значение c.

proc transpose data=LENDING_TEMPLATE out=tall ;
  by geography ar_no ;
run;

data tall ;
  set tall ;
  date = input(_name_ , 32.) + '30DEC1899'd ;
  format date date9. ;
  drop _name_;
run;

На этом можно остановиться, поскольку теперь у вас есть полезный набор данных, в котором значения даты находятся в переменной, а не скрываются в метаданных (имя переменной).

Чтобы вернуться к исходному широкому макету, просто добавьте еще один PRO C TRANSPOSE и скажите ему использовать DATE в качестве переменной ID.

 proc transpose data=tall out=wide ;
    by geography ar_no ;
    id date;
    var col1;
 run;
...