Как перейти от годового конца года к среднегодовому в SAS - PullRequest
0 голосов
/ 06 сентября 2018

В настоящее время я работаю в SAS и использую массивы следующим образом:

Data Test;
input Payment2018-Payment2021;
datalines;

10 10 10 10
20 20 20 20
30 30 30 30
;
run;

По моему мнению, это автоматически предполагает ограничение: начало года или конец года (поправьте меня, если я ошибаюсь, пожалуйста)

Итак, если бы я хотел сказать, что это июньские данные и платежи будут увеличиваться каждые 9 месяцев на 50%, я ищу способ, чтобы мой код мог распознать, что мои годы идут с конца июня до следующего конец июня

Например, если бы я хотел сказать

Data Payment_Pct;
set test;

lastpayrise = "31Jul2018";

array payment:
array Pay_Inc(2018:2021) Pay_Inc: ;

Pay_Inc2018 = 0;
Pay_Inc2019 = 2; /*2 because there are two increments in 2019*/
Pay_Inc2020 = 1;
Pay_Inc2021 = 1;

do I = 2018 to 2021;

    if i = year(pay_inc) then payrise(i) * 50% * Pay_Inc(i);

end;

run;

Это хорошо для меня, чтобы вручную сделать это для одной записи, но для моего универа, мне понадобится алгоритм, чтобы разобраться с этим самостоятельно, и я сейчас читаю в intck, но любая помощь будет признательна!

P.s. Было бы здорово иметь алгоритм, который создает следующее

Pay_Inc2019 Pay_Inc2020 Pay_Inc2021
1           2           1

ИЛИ было бы замечательно узнать, как SAS работает при настройке массива на 2018: 2021, предполагает ли он конец года или вы можете установить его на середину года или?

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Относительно input Payment2018-Payment2021; не существует автоматического предположения о годичности или календаре. Числа 2018 и 2021 являются границами для нумерованного списка диапазонов

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

Значение чисел с 2018 по 2021 зависит от программиста. Вы указываете, что переменные соответствуют июньскому платежу в пронумерованном году.

Вам нужно будет повторить дату, используя 9-месячные шаги, и увеличить счетчик на основе года, в котором эта дата выпадает.

Пример кода

Динамически адаптируется к именам переменных в массиве.

data _null_;

  array payments payment2018-payment2021;
  array Pay_Incs pay_inc2018-pay_inc2021; * must be same range numbers as payments;

  * obtain variable names of first and last element in the payments array;
  lower_varname = vname(payments(1));
  upper_varname = vname(payments(dim(payments)));

  * determine position of the range name numbers in those variable names;
  lower_year_position = prxmatch('/\d+\s*$/', lower_varname);
  upper_year_position = prxmatch('/\d+\s*$/', upper_varname);

  * extract range name numbers from the variable names;
  lower_year = input(substr(lower_varname,lower_year_position),12.);
  upper_year = input(substr(upper_varname,upper_year_position),12.);

  * prepare iteration of a date over the years that should be the name range numbers;
  date = mdy(06,01,lower_year); * june 1 of year corresponding to first variable in array;

  format date yymmdd10.;

  do _n_ = 1 by 1; * repurpose _n_ for an infinite do loop with interior leave;
    * increment by 9-months;
    date = intnx('month', date, 9);

    year = year(date);    
    if year > upper_year then leave;

    * increment counter for year in which iterating date falls within;
    Pay_Incs( year - lower_year + 1 ) + 1;
  end;

  put Pay_Incs(*)=;
run;

Счетчик приращений примечаний

В этом утверждении есть что распаковать

    Pay_Incs( year - lower_year + 1 ) + 1;
  • + 1 в конце оператора увеличивает адресный элемент массива на 1 и является синтаксисом для SUM оператора

    переменная + выражение

    Оператор sum эквивалентен использованию функции SUM и оператора RETAIN, как показано здесь: retain variable 0; variable=sum(variable,expression);

  • year - lower_year + 1 вычисляет индекс base-1 массива 1..N, который обращается к соответствующей переменной в списке именованных диапазонов pay_inc<lower_year>-pay_inc<upper_year>

  • Pay_Incs( <computed index> ) выбирает переменную оператора SUM

0 голосов
/ 06 сентября 2018

Это прекрасный пример использования функции intnx(). intnx() будет вашим лучшим другом, когда дело доходит до выравнивания дат.

В традиционном календаре год начинается с 01JAN. В вашем календаре год начинается с 01JUN. Разница между этими двумя датами составляет ровно 6 месяцев. Мы хотим сместить нашу дату так, чтобы год начался 01JUN. Это позволит вам взять часть года из даты и определить, в каком году вы находитесь в новом календаре.

data want;
    format current_cal_year
           current_new_year year4.
    ;

    current_cal_year = intnx('year', '01JUN2018'd, 0, 'B');
    current_new_year = intnx('year.6', '01JUN2018'd, 1, 'B');
run;

Обратите внимание, что мы сместились current_new_year на один год. Чтобы проиллюстрировать почему, давайте посмотрим, что произойдет, если мы не сдвинем его на один год.

data want;
    format current_cal_year
           current_new_year year4.
    ;

    current_cal_year = intnx('year', '01JUN2018'd, 0, 'B');
    current_new_year = intnx('year.6', '01JUN2018'd, 0, 'B');
run;

current_new_year показывает 2018, но мы действительно в 2019. В течение 5 месяцев в году это значение будет правильным. С июня по декабрь значение года будет неверным. При смещении на один год у нас всегда будет правильный год, связанный с этим значением даты. Посмотрите на это с разными месяцами года, и вы увидите, что часть года остается верной во времени.

data want;
    format cal_month date9.
           cal_year
           new_year year4.
    ;

    do i = 0 to 24;
        cal_month = intnx('month', '01JAN2016'd, i, 'B');
        cal_year = intnx('year', cal_month, i, 'B');
        new_year = intnx('year.6', cal_month, i+1, 'B');
        year_not_same = (year(cal_year) NE year(new_year) );
        output;
    end;

    drop i;
run;
...