2015-04-29 4 views
3

Рассмотрим набор данных test в следующем виде:Разница в датах в SAS группой

Group Date 
    1  05JAN2014 
    1  08JAN2014 
    1  14JAN2014 
    2  05JAN2013 
    2  10FEB2015 
    2  27FEB2015 

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

data test; 
    datediff = dif(Date); 
    run; 

Как бы я только взять разницу между датами в одной группе? Кроме того, есть ли способ изменить разницу между последней и первой датами в каждой группе?

ответ

4

Начиная с этого:

data test; 
    datediff = dif(Date); 
    run; 

Давайте обратимся ваш isues по одному. Во-первых, добавив заявление set и инструкцию by, мы также можем добавить first и last, чтобы вы могли определить, где вы находитесь. Предполагается, что он уже отсортирован by group.

data test2; 
    set test; 
    by group; 
    datediff=dif(date); 
run; 

Это не работает по-другому (при условии, что у вас было задание типа изначально, во всяком случае). Но теперь у вас есть новые возможности.

Во-первых, хотя вы можете использовать dif, я рекомендую метод retain для этого. Вы можете более легко увидеть, что он делает, и избежать некоторых распространенных ошибок: в частности, lag и dif фактически не сравниваются с предыдущей записью - они создают очередь и сравниваются с тем, что может привести к осложнениям при использовании условных операторов.

data test2; 
    set test; 
    by group; 
    retain last_date; 
    if first.group then last_date=0; 
    datediff = date - last_date; 
    output; 
    last_date = date; 
run; 

Это делает то же самое, что и раньше - сравнивает предыдущее значение текущего значения - но делает его немного легче видеть, и мы добавим в качестве опции для сброса переменной last_date когда first.group верно - значение мы находимся в первой строке нового значения группы. Я не буду отбрасывать какие-либо из этих промежуточных переменных, но в производственном коде вы можете и должны. retain означает, что значение будет сохраняться через строки (вместо того, чтобы сбрасываться каждый раз, когда вы получаете новую строку).

Теперь, когда у вас есть одна переменная, отслеживающая значение предыдущей строки date, довольно легко надеяться увидеть, как мы можем сделать это для первой и последней разницы.

data test2; 
    set test; 
    by group; 
    retain last_date orig_date; 
    if first.group then do; 
    last_date=0; 
    orig_date=date; **new; 
    end; 
    datediff = date - last_date; 
    if last.group then group_datediff = date-orig_date; **new; 
    output; 
    last_date = date; 
run; 

Теперь мы сделали то же самое, что и раньше - но мы Переустановка orig_date каждый раз, когда мы видим first.group и вычисления group_datediff, когда мы попали last.group.

3

Ниже приведено использование метода lag и новой функции ifn, (ifn входит в SAS 9.2 или новее). Будьте осторожны с функцией задержки, так как иногда это может привести к неожиданным результатам. См. this paper для более подробной информации об этом.

*Data must be sorted to use BY groups; 
proc sort data=have; by group date;run; 

data want; 
    set have; 
    by group; 
    dateDiff = ifn(first.group, . , dif(date)); 

    retain firstDate; 
    if first.group then firstDate = date; 
    if last.group then dateDiff_all = date - firstDate; 
run; 
+2

Вы можете вычислить dateDiff с помощью функции 'dif' вместо того, чтобы получать задержанную дату и вычитать ее с текущей даты (' dateDiff = ifn (first.group,., Dif (date)); ' – Longfish

+0

Хорошая мысль @ Кит - отредактирован, чтобы быть более элегантным :-). –

2

Здесь представлено решение с использованием proc sql и группового оператора с итоговыми функциями min и max.

Это даст вам разницу в каждой группе для первой и последней дат.

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

proc sql; 
    create table want as select 
    group, 
    max(date) - min(date) as datediff 
    from have 
    group by group; 
quit; 
+0

@Joe Это прекрасно работает в большинстве вариантов SQL, которые я использовал (только что протестировал в mySQL и MSSQL, чтобы убедиться, что я не сходил с ума). Я не уверен, что вы пытаетесь сказать, так как select * does * соответствует группе ... (т.е. select = group, group by = group). –

+0

Хм. Я, должно быть, неправильно понял это - изначально я читал его как select *. К сожалению. – Joe

Смежные вопросы