2015-10-19 4 views
0

У меня есть данные, как показано ниже.sas macro do loop Сколько дней в году

Мне нужно показать каждому человеку, сколько дней живет в год жизни.

ı пробовал много делать петли и если утверждения в макросе.

ı много работал, но я не мог сделать это, мои руки опустели, и мое сердце сломалось.

*name STARTDATE ENDDATE 

*AAA 17.10.2012 21.11.2013 

*BBB 10.05.2014 15.09.2015 

*CCC 06.04.2010 05.05.2013 

*DDD 07.02.2011 07.02.2013 

*EEE 30.03.2013 30.01.2014 

*FFF 01.01.2010 06.05.2010 

В результате я это нужно

*name STARTDATE ENDDATE DayIn2010 DayIn2011 DayIn2012 DayIn2013 DayIn2014 DayIn2015 

*AAA 17.10.2012 21.11.2013 0 0 75 325 0 0 

*BBB 10.05.2014 15.09.2015 0 0 0 0 235 258 

*CCC 06.04.2010 05.05.2013 269 365 365 125 0 0 

*DDD 07.02.2011 07.02.2013 0 327 365 38 0 0 

*EEE 30.03.2013 30.01.2014 0 0 0 276 30 0 

*FFF 01.01.2010 06.05.2010 125 0 0 0 0 0 

могли бы вы мне помочь?

+0

Просьба поделиться кодом, который вы пробовали. Даже если он не работает, может потребоваться только небольшая корректировка. – user667489

+0

Кроме того, вам абсолютно необходимо использовать расширенный формат, который вы указали? Для большинства вещей я предлагаю длинный формат, т. Е. Одну колонку за год и одну строку на человека в год с количеством дней, в течение которых они проживали в этом году. – user667489

+0

привет пользователь667489. , коды находятся на моем рабочем компьютере. если вам нужно завтра, я отправлю. нет, широкий формат не нужен, длинный формат был оценен. но не мог понять, как вы можете это сделать. im очень новичок в этом. – user3375397

ответ

1

Вот как вы можете это сделать. Макросы не требуется, только шаг данных делать-цикл:

data have; 
input name $3. (STARTDATE ENDDATE) (+1 ddmmyy10.); 
format STARTDATE ENDDATE ddmmyy10.; 
cards; 
AAA 17.10.2012 21.11.2013 
BBB 10.05.2014 15.09.2015 
CCC 06.04.2010 05.05.2013 
DDD 07.02.2011 07.02.2013 
EEE 30.03.2013 30.01.2014 
FFF 01.01.2010 06.05.2010 
; 
run; 

data want; 
    set have; 
    format YEAR_START YEAR_END ddmmyy10.; 
    do YEAR = 2010 to 2015; 
     YEAR_START = mdy(1,1,YEAR); 
     YEAR_END = mdy(12,31,YEAR); 
     DAYS_ALIVE = max(0,min(ENDDATE, YEAR_END) - max(STARTDATE,YEAR_START) + 1); 
     output; 
    end; 
run; 

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

+0

Я думаю, мне нужен этот широкий формат. потому что мои данные немного большие, и это решение делает мои данные в 10 раз дольше. но большое спасибо за этот блестящий ответ. – user3375397

+0

Если вы не выполняете последующую сортировку или другую обработку, вы можете создать представление вместо этого - просто измените 'data want;' на 'data want/view = want;'. Таким образом, он не займет лишнего дискового пространства. – user667489

+0

Вы также можете избавиться от всех строк с нулевыми днями, изменив 'output;' на 'if DAYS_ALIVE> 0 then output;', что немного уменьшило бы его на основе данных примера. – user667489

1

Вот еще один вариант, который вам может не понадобиться, чтобы знать о начале и конце года.

data have; 
input name $3. (STARTDATE ENDDATE) (+1 ddmmyy10.); 
format STARTDATE ENDDATE ddmmyy10.; 
cards; 
AAA 17.10.2012 21.11.2013 
BBB 10.05.2014 15.09.2015 
CCC 06.04.2010 05.05.2013 
DDD 07.02.2011 07.02.2013 
EEE 30.03.2013 30.01.2014 
FFF 01.01.2010 06.05.2010 
; 
run; 

data s1; 
set have; 
do dt=startdate to enddate; 
output; 
end; 
run; 

ods output CrossTabFreqs=s2 (where=(not missing(dt) and not missing(name)) keep=name dt frequency); 
proc freq data=s1; 
tables name*dt/
    NOROW 
     NOCOL 
     NOPERCENT 
     NOCUM; 
format dt year4.; 
run; 

proc sort data=s2; 
by name; 
run; 

PROC TRANSPOSE DATA=s2 
    OUT=want(drop=_name_ _label_) 
    PREFIX=DaysIn 
; 
    BY name; 
    ID dt; 
    VAR Frequency; 

RUN; QUIT 
Смежные вопросы