Таблица транспонирования SAS с несколькими вариантами VAR - PullRequest
1 голос
/ 04 июня 2019

У меня есть таблица, которая выглядит следующим образом:

ID     NAME    TYPE        DATE_VALUE    STRING_VALUE      NUMBER_VALUE  
1    revenue report_date    01jan2018
1    revenue    name                     Revenue_12m
1    revenue    code                                           1100
1    revenue    sum                                           6000000

Я хочу, чтобы она выглядела так:

ID     NAME     report_date     name          code       sum
1    revenue     01jan2018    Revenue_12m     1100     6000000

Мой код, который дает неправильный результат (3 строки):

proc transpose data=tab1 out=tab2;
by id name;
var number_value string_value date_value;
id type;
run;

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Рассмотрим условное агрегирование в SQL, предполагая, что ваши типы представляют собой несколько элементов:

proc sql;
    create table output as
    select ID, NAME,
           MAX(case when TYPE = 'name' then STRING_VALUE else "" end) AS report_name,
           MAX(case when TYPE = 'report_date' then DATE_VALUE else . end) AS report_date format=date9.,
           MAX(case when TYPE = 'code' then NUMBER_VALUE else . end) AS code,
           MAX(case when TYPE = 'sum' then NUMBER_VALUE else . end) AS sum
    from raw
    group ID, NAME;
quit;

Ввод

data raw;
    infile datalines delimiter=',' DSD; 
    length NAME $ 7 TYPE $ 11 STRING_VALUE $11 NUMBER_VALUE 7;
    input ID NAME $ TYPE $ STRING_VALUE $ NUMBER_VALUE DATE_VALUE date9.;
    format DATE_VALUE DATE9.;
    datalines;
1,revenue,report_date,,.,01jan2018
1,revenue,name,Revenue_12m,.,.
1,revenue,code,,1100,.
1,revenue,sum,,6000000,.
;

Выход

ID    NAME   report_name   report_date  code     sum 
 1 revenue   Revenue_12m     01JAN2018  1100 6000000 
0 голосов
/ 04 июня 2019

Вы можете решить эту проблему, запустив PROC TRANSPOSE три раза, по одному для каждого типа данных. Вам также необходимо удалить конфликт из-за переменной с именем NAME.

Итак, сначала давайте создадим данные вашего примера.

data have;
  input ID $ xNAME $ TYPE :$32. DATE_VALUE :date. STRING_VALUE :$50. NUMBER_VALUE;
  format date_value date9.;
cards;
1 revenue report_date 01jan2018 . .
1 revenue name        . Revenue_12m .
1 revenue code        . . 1100
1 revenue sum         . . 6000000
;

Теперь мы можем сгенерировать три отдельных набора данных.

proc transpose data=have out=dates(drop=_name_);
  where not missing(date_value);
  by id xname;
  var date_value;
  id type;
run;
proc transpose data=have out=strings(drop=_name_);
  where not missing(string_value);
  by id xname;
  var string_value;
  id type;
run;
proc transpose data=have out=numbers(drop=_name_);
  where not missing(number_value);
  by id xname;
  var number_value;
  id type;
run;

И объединить их.

data want;
  merge dates strings numbers;
  by id xname;
run;

Обратите внимание, что этот метод не будет создавать столбцы для значений TYPE, которые всегда отсутствуют. Вы можете изменить операторы WHERE, чтобы вместо них перечислять значения типа TYPE, которые вместо этого используют эту конкретную переменную источника. Но тогда вам нужно заранее знать список возможных значений TYPE, в таком случае почему бы просто не написать шаг данных для выполнения преобразования. Примерно так:

data want;
  length id $8 xname $50 report_date 8 name $50 code sum 8 ;
  format report_date date9.;
  do until(last.xname);
    set have ;
    by id xname ;
    select (type);
      when ('report_date')  report_date=date_value;
      when ('name')  name=string_value;
      when ('code')  code=number_value;
      when ('sum')  sum=number_value;
      otherwise put 'WARNING: Unknown type. ' id= xname= type= ;
    end;
  end;
  drop type date_value string_value number_value;
run;

Если у вас есть метаданные о ваших данных, вы можете использовать их для определения переменных и создания оператора SELECT.

...