SAS Pro c Импорт CSV и отсутствующих данных - PullRequest
1 голос
/ 29 января 2020

Итак, я пытаюсь импортировать некоторые наборы данных в SAS и присоединиться к ним, единственная проблема заключается в том, что я получаю эту ошибку после присоединения к ним -

    proc import datafile='filepath/datasetA.csv'
    out = dataA
    dbms= csv
    replace;
    run;


    proc import datafile='filepath\datasetB.csv'
    out = dataB
    dbms= csv
    replace;
    run;



    /* combine them all into one dataset*/


    data DataC;
    set &dataA. &dataB;

    run;



    ERROR: Variable column_k has been defined as both character and numeric

Столбец, о котором идет речь, выглядит примерно так в оба набора данных, к которым я пытаюсь присоединиться -

+----------+
| column_k |
+----------+
| 0        |
| 1        |
| 5        |
| 4        |
| NA       |
| NA       |
| 4        |
| 3        |
| NA       |
+----------+

По сути, я хотел бы импортировать данные NA в этом столбце как «отсутствующие», если это возможно? Мне нужно, чтобы весь столбец оставался цифрой c, так как я планирую выполнить некоторые математические операции с данными в этом столбце далее.

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 29 января 2020

Если вы sh продолжите использовать Proc IMPORT, вам нужно будет убедиться, что столбцы напечатаны одинаково. В вашем случае вы знаете, что column_k должно быть цифрой c, поэтому шаг DATA может преобразовать значения символов в цифру c с помощью функции INPUT.

proc import … out = dataA;
proc import … out = dataB;

data dataA;
  set dataA;
  _num = input(column_k, best12.);
  drop column_k;
  rename _num = column_k;
run;

data dataB;
  set dataB;
  _num = input(column_k, best12.);
  drop column_k;
  rename _num = column_k;
run;

data want;
  set dataA dataB;
run;

В большем Несоответствующие областям типы данных для имени столбца могут возникнуть в сценарии, например при работе с многолетним импортом.

Предположим, что более старые данные не могут быть перечитаны, а более новые данные имеют другой тип столбца.

Для случая нумерации чисел c, один из подходов состоит в том, чтобы иметь макрос, который записывает исходный код, который при необходимости преобразует указанные переменные из символов в числа c.

Пример:

%enforce_num (perm.loans2015, age amount remaining, out=work.loans2015)
%enforce_num (perm.loans2016, age amount remaining, out=work.loans2016)
%enforce_num (perm.loans2017, age amount remaining, out=work.loans2017)

data loans_3yrs; 
  set work.loans2015-loans2017;
run;

Возвращаясь к более простому случаю:

proc import … out = dataA;
proc import … out = dataB;

%enforce_num(dataA, column_k)
%enforce_num(dataB, column_k)

data want;
  set dataA dataB;
run;

Как бы выглядел макрос enforce_num? Это должно было бы:

  • сканировать метаданные входного набора данных
  • определить, является ли переменная одной из указанных и имеет тип символов
    • записать исходный код в преобразовать переменную в число c
    • сохранить исходный порядок переменных
%macro enforce_num(data, vars, out=&data);

  /*
   * Arguments:
   *   data - name of input data set
   *   vars - space separated list of variables that must be numeric, convert type if necessary
   *   out  - name of output data set, default same as input data set
   *
   * Output:
   *   - Unchanged data set if data and out are the same and no conversion needed
   *   - Changed data set if some columns in data need conversion to numeric
   *     - replaces data if out is same as data
   *     - replaces out if out is different then data
   *     - the column order of the changed data set will be the same as the original data set
   */

  %local dsid index index2 vars varname vartype varnames debug;

  %let index2 = 0;  %* number of variables determined to be requiring conversion;
  %let debug = 0;

  %if &debug %then %put NOTE: &SYSMACRONAME: data=%superq(data);

  %let dsid = %sysfunc(open(&data));
  %if &dsid %then %do;
    %do index = 1 %to %sysfunc(attrn(&dsid, nvars));
      %let varname = %sysfunc(varname(&dsid, &index));

      %let varnames = &varnames &varname;

      %if %sysfunc(indexw(&varname, &vars)) %then %do;
        %if C = %sysfunc(vartype(&dsid, &index)) %then %do;
          %* Data contains character variable requiring enforcement;
          %let index2 = %eval(&index2+1);
          %local convert&index2;
          %let convert&index2 = &varname;

          %let varnames = &varnames ___&index2 ;   %* Variables that will be converted will be named __<#> during conversion;
        %end;
      %end;
    %end;
    %let dsid = %sysfunc(close(&dsid));
  %end;
  %else
    %put %sysfunc(sysmsg());

  %*put NOTE: &=vars;
  %*put NOTE: &=varnames;

  %if &index2 = 0 %then %do;
    %* No columns need to be converted to numeric, copy to out if necessary;
    %if &data ne &out %then %do;
      data &out;
        set &data;
      run;
    %end;
    %return;
  %end;

  %* Some columns need to be converted to numeric;
  %* Ensure the converted column is at the same position (varnum) as in the original data set;

  data &out;
    retain &varnames;

    set &data;

    %do index = 1 %to &index2;
      ___&index = input(&&convert&index,?? best12.);
    %end;

    drop
      %do index = 1 %to &index2;
        &&convert&index
      %end;
    ;

    rename
      %do index = 1 %to &index2;
        ___&index = &&convert&index
      %end;
    ;
  run;

  %put NOTE: ------------------------------------------------;
  %put NOTE: &data has been subjected to numeric enforcement.;
  %put NOTE: ------------------------------------------------;
%mend enforce_num;
2 голосов
/ 29 января 2020

proc import - это процедура угадывания, которая работает путем изучения нескольких строк данных. Это проблема, потому что ячейки данных Excel не имеют типа данных вообще. Столбец может содержать текст, дату, дату и время в числовых значениях c в разных ячейках.

Поэтому лучше использовать оператор infile с указанными типами переменных:

filename input 'filepath/datasetA.csv';

data dataA;
   infile input truncover firstobs=2/*reads from the second line*/;
   input column_k;/*here you should specify input variables. If you want to read column_k as character, use : "input column_k $100." with specified length*/
run;

filename input clear;

Input ( CSV-файл):

+----------+
| column_k |
+----------+
| 0        |
| 1        |
| 5        |
| 4        |
| NA       |
| NA       |
| 4        |
| 3        |
| NA       |
+----------+

Вывод (данные набора данных sA):

+----------+
| column_k |
+----------+
|        0 |
|        1 |
|        5 |
|        4 |
|        . |
|        . |
|        4 |
|        3 |
|        . |
+----------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...