Вопрос или проблема
У меня есть этот код на R, который создает датафрейм календаря:
library(lubridate)
library(dplyr)
start_date <- ymd("2000-01-01")
end_date <- today()
date_seq <- seq(start_date, end_date, by = "day")
date_df <- data.frame(date = date_seq) %>%
mutate(
calendar_year = year(date),
calendar_month = month(date),
day = day(date),
day_of_week = wday(date, label = TRUE, abbr = FALSE),
fiscal_year = ifelse(month(date) >= 4,
paste0(year(date), "-", year(date) + 1),
paste0(year(date) - 1, "-", year(date))),
fiscal_month = (month(date) - 3) %% 12 + 1,
days_since_start_of_current_calendar_year = as.integer(date - floor_date(date, "year") + 1),
days_since_start_of_current_fiscal_year = as.integer(date - floor_date(date %m+% months(3), "year") %m-% months(3) + 1)
)
head(date_df)
Это выглядит так:
date calendar_year calendar_month day day_of_week fiscal_year fiscal_month days_since_start_of_current_calendar_year days_since_start_of_current_fiscal_year
1 2000-01-01 2000 1 1 Saturday 1999-2000 11 1 93
2 2000-01-02 2000 1 2 Sunday 1999-2000 11 2 94
3 2000-01-03 2000 1 3 Monday 1999-2000 11 3 95
4 2000-01-04 2000 1 4 Tuesday 1999-2000 11 4 96
5 2000-01-05 2000 1 5 Wednesday 1999-2000 11 5 97
6 2000-01-06 2000 1 6 Thursday 1999-2000 11 6 98
Я задаюсь вопросом, может ли этот же код быть создан в SAS?
Я попытался перевести логику строчка за строчкой здесь:
data date_df;
format date date9.;
date="01JAN2000"d;
do while (date <= today());
calendar_year = year(date);
calendar_month = month(date);
day = day(date);
day_of_week = put(date, downame.);
if month(date) >= 4 then do;
fiscal_year = put(year(date), 4.) || '-' || put(year(date) + 1, 4.);
end;
else do;
fiscal_year = put(year(date) - 1, 4.) || '-' || put(year(date), 4.);
end;
fiscal_month = mod(month(date) - 3, 12) + 1;
days_since_start_of_current_calendar_year = date - intnx('year', date, 0, 'B') + 1;
days_since_start_of_current_fiscal_year = date - intnx('year', intnx('month', date, 3), 0, 'B') + 1;
output;
date = date + 1;
end;
drop date;
run;
proc sort data=date_df;
by date;
run;
proc print data=date_df(obs=10);
run;
Можно ли использовать макросы SAS для этого? Или существует какой-то другой PROC, который можно использовать в SAS?
Ответ или решение
Создание календаря в SAS – это совершенно возможно и может быть выполнено с использованием ваших текущих знаний о программировании. Вы уже начали отлично переводить код R в код SAS, и я помогу вам завершить этот процесс.
Ваше начальное решение почти правильное, но давайте немного улучшить его, чтобы убедиться, что данные правильно генерируются. В SAS нет встроенной функции, аналогичной lubridate
, но мы можем добиться нужного результата с помощью обработки дат и логики, которая уже есть в вашем коде.
Вот полное решение:
data date_df;
/* Определяем формат для даты */
format date date9.;
/* Инициализируем дату 1 января 2000 года */
date = '01JAN2000'd;
/* Цикл для генерации дат до сегодняшнего дня */
do while (date <= today());
/* Вычисляем календарный год и месяц */
calendar_year = year(date);
calendar_month = month(date);
/* Определяем день и день недели */
day = day(date);
day_of_week = put(date, downame.);
/* Определяем финансовый год */
if month(date) >= 4 then do;
fiscal_year = put(year(date), 4.) || '-' || put(year(date) + 1, 4.);
end;
else do;
fiscal_year = put(year(date) - 1, 4.) || '-' || put(year(date), 4.);
end;
/* Определяем финансовый месяц */
fiscal_month = mod(month(date) - 3, 12) + 1;
/* Количество дней с начала текущего календарного года */
days_since_start_of_current_calendar_year = date - intnx('year', date, 0, 'B') + 1;
/* Количество дней с начала текущего финансового года */
days_since_start_of_current_fiscal_year = date - intnx('year', intnx('month', date, 3), 0, 'B') + 1;
/* Выводим текущую строку в дата-сет */
output;
/* Увеличиваем дату на один день */
date + 1;
end;
/* Удаляем временную переменную */
drop date;
run;
/* Сортируем данные по дате */
proc sort data=date_df;
by date;
run;
/* Печатаем первые 10 наблюдений для проверки результатов */
proc print data=date_df(obs=10);
run;
Объяснение кода
- Формат даты: Используем
format date date9.;
для отображения даты в стандартном формате. - Инициализация даты: Устанавливаем начальную дату
'01JAN2000'd;
. - Цикл do while: Этот цикл будет продолжаться до тех пор, пока дата меньше или равна сегодняшнему дню.
- Вычисления: Для каждого дня рассчитываются значения календарного года, месяца, дня, дня недели, финансового года, финансового месяца и количества дней с начала текущего календарного и финансового года.
- Вывод и кичка: Используем
output
для вывода строки данных для каждого дня, и увеличиваем дату на один день в конце итерации. - Сортировка и печать: В конце сортируем полученные данные и печатаем первые десять записей для проверки.
Использование макросов
Использование макросов в SAS для этой задачи не обязательно, однако при необходимости автоматизировать процесс или генерировать календарь для разных диапазонов дат, макросы могут оказаться полезными. Например, вы можете создать макрос для установки начальной и конечной дат.
В итоге ваш скрипт создает календарь, аналогичный тому, который был создан в R, но с использованием функционала SAS. Если у вас есть дополнительные вопросы или нужно расширить функционал, не стесняйтесь спрашивать!