Вычислить среднее значение за последние x лет

#sas #proc-sql

#sas #proc-sql

Вопрос:

У меня есть следующие данные

 Date         value_idx
2002-01-31    .
2002-01-31   24.533
2002-01-31   26.50
2018-02-28   25.2124
2019-09-12   22.251
2019-01-31   24.214
2019-05-21   25.241
2019-05-21    .
2020-05-21   25.241
2020-05-21   23.232
  

Мне нужно было бы рассчитать среднее значение value_idx за последние 3 года и 7 лет.
Сначала я попытался рассчитать его следующим образом:

 proc sql;
create table table1 as
select date, avg(value_idx) as avg_value_idx
from table
group by date;
quit;
  

Проблема в том, что я не знаю, как рассчитать среднее значение value_idx не за каждый месяц, а за последние два года. Поэтому я думаю, что я должен извлечь год, сгруппировать по нему, а затем вычислить среднее значение.
Я надеюсь, что кто-нибудь из вас сможет мне в этом помочь.

Комментарии:

1. Пожалуйста, объясните, что вы хотите более четко. Не могли бы вы предоставить результаты для опубликованных вами выборочных данных. Если вам просто нужно среднее значение за 7 лет до сегодняшнего дня, просто используйте предложение WHERE для фильтрации наблюдений с датой> = ’01JAN2013′ .

2. Мне нужно было бы рассмотреть среднее значение value_idx, вычисляющее его за последние два года (2019 и 2018).

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

4. это должно быть всего одно значение, так как я должен взять среднее значение за 2018 и 2019 годы (последние два года), начиная с самого последнего года (который в наборе данных равен 2020).

5. Это возможно в PROC SQL , но я не рекомендую использовать это для подобных вещей — если у вас есть причина, которую вы должны использовать PROC SQL конкретно, измените сообщение, чтобы включить это.

Ответ №1:

Вы можете использовать CASE, чтобы решить, какие записи вносят вклад в какое СРЕДНЕЕ значение. Вам необходимо уточнить, что вы подразумеваете под последними 2 или последними 7 годами. Этот код найдет значение максимальной даты, а затем сравнит год этой даты с годом других дат.

 select 
 mean(case when year(max_date)-year(date) < 2 then value_idx else . end) as mean_yr2 
,mean(case when year(max_date)-year(date) < 7 then value_idx else . end) as mean_yr7
from have,(select max(date) as max_date from have)
;
  

Результаты

 mean_yr2  mean_yr7
------------------
 24.0358   24.2319
  

Ответ №2:

Лучший способ сделать что-то подобное в SAS — использовать собственные процедуры, поскольку у них много функций, связанных с группировкой.

В этом случае мы используем форматы с несколькими метками для управления группировкой. Я предполагаю, что вы имеете в виду «последние три года», как в календаре 2018/2019/2020 и «Последние семь лет», как в календаре 2014-2020. Предположительно, вы можете увидеть, как изменить это для других периодов времени — до тех пор, пока вы не пытаетесь установить период времени относительно каждой точки данных.

Мы создаем формат, в котором используется MULTILABEL опция (которая позволяет распределять точки данных по нескольким категориям) и NOTSORTED опция (позволяющая нам принудительно упорядочивать метки, в противном случае СЕМЬ раньше, чем ТРИ).

Затем мы используем его в PROC TABULATE, включив его с MLF помощью (MultiLabel Format) и preloadfmt order=data который снова сохраняет правильность упорядочения. При этом создается отчет только с двумя средними значениями.

 data have;
informat date yymmdd10.;
input Date value_idx;
datalines;
2002-01-31    .
2002-01-31   24.533
2002-01-31   26.50
2017-02-28   25.2124
2017-09-12   22.251
2018-01-31   24.214
2018-05-21   25.241
2019-05-21    .
2020-05-21   25.241
2020-05-21   23.232
;;;;
run;

proc format;
  value yeartabfmt (multilabel notsorted)
    '01JAN2018'd-'31DEC2020'd = 'Last Three Years'
    '01JAN2014'd-'31DEC2020'd = 'Last Seven Years'
     other=' '
   ;
quit;

proc tabulate data=have;
  class date/mlf preloadfmt order=data;
  var value_idx;
  format date yeartabfmt.;
  tables date,value_idx*mean;
run;