Как построить простой линейный сюжет в SAS

Мои данные структурированы следующим образом (это только примерные данные, поскольку исходные данные являются секретными)

id | crime   | location | crimedate
------------------------------
1  | Theft   | public   | 2019-01-04
1  | Theft   | public   | 2019-02-06
1  | Theft   | public   | 2019-02-20
1  | Theft   | private  | 2019-03-10
1  | Theft   | private  | 2019-03-21
1  | Theft   | public   | 2019-03-01
1  | Theft   | private  | 2019-03-14
1  | Theft   | public   | 2019-06-15
1  | Murder  | private  | 2019-01-04
1  | Murder  | private  | 2019-10-20
1  | Murder  | private  | 2019-11-18
1  | Murder  | private  | 2019-01-01
1  | Assault | private  | 2019-03-19
1  | Assault | private  | 2019-01-21
1  | Assault | public   | 2019-04-11
1  | Assault | public   | 2019-01-10
…  | …       | …        | … 

Моя цель - создать линейный сюжет (сюжет временного ряда), показывающий, как за три года изменились цифры трех преступлений. Поэтому на оси X я хотел бы показать месяцы (1-12), а на оси Y количество преступлений в каждом месяце. Там должно быть две строки (по одной для каждого места).

Я начал с этого кода:

DATA new;
 SET old;
 month=month(datepart(crimedate));
RUN;

PROC sgplot DATA=new;
    series x=month y=no_of_crimes / group=location;
run;

Но я понятия не имею, как я могу агрегировать количество преступлений в месяц. Может ли кто-нибудь дать мне подсказку? Я искал в Интернете решение, но обычно в примерах просто используются данные, которые уже агрегированы.

3 ответа

Решение

Процедуры SG будут агрегировать значения оси Y для VBAR или же HBAR заявление. Та же самая совокупная информация, отображаемая в SERIES утверждение должно быть из априорного вычисления агрегата, легко сделать с Proc SUMMARY,

Кроме того, чтобы отобразить счетчики для каждого преступления в отдельном визуальном элементе, вы бы хотели BY CRIME заявление или Proc SGPANEL с участием PANELBY crime,

Значение даты и времени преступления не нужно преобразовывать в значение даты, вы можете использовать соответствующие datetime формат в процедурах, и они будут автоматически объединяться на основе отформатированного значения.

Пример с некоторыми данными смоделированного преступления:

data have;
  do precinct = 1 to 10;
    do date = '01jan2018'd to '31dec2018'd;
      do seq = 1 to 20*ranuni(123);
        length crime $10 location $8;
        crime = scan('theft,assault,robbery,dnd', ceil(4*ranuni(123)));
        location = scan ('public,private', ceil(2*ranuni(123)));
        crime_dt = dhms(date,0,0,floor('24:00't*ranuni(123)));
        output;      
      end;
    end;
  end;
  drop date;
  format crime_dt datetime19.;
run;

* shorter graphs for SO answer;
ods graphics / height=300px; 

proc sgplot data=have;
  title "VBAR all crimes combined by location";
  vbar crime_dt 
  / group=location
    groupdisplay=cluster
  ;

  format crime_dt dtmonyy7.;
run;

proc sgpanel data=have;
  title "VBAR crime * location";
  panelby crime;
  vbar crime_dt 
  / group=location
    groupdisplay=cluster
  ;

  format crime_dt dtmonyy7.;
run;

proc summary data=have noprint;
  class crime_dt crime location;
  format crime_dt dtmonyy7.;
  output out=freqs;
run;

proc sgplot data=freqs;
  title "SERIES all crimes,summary _FREQ_ * location";
  where _type_ = 5;
  series x=crime_dt y=_freq_ / group=location;
  xaxis type=discrete;
run;

proc sgpanel data=freqs;
  title "SERIES all crimes,summary _FREQ_ * crime * location";
  where _type_ = 7;
  panelby crime;
  series x=crime_dt y=_freq_ / group=location;
  rowaxis min=0;
  colaxis type=discrete;
run;

Если вы хотите сгруппировать по местоположению без определения по типу преступления:

proc sql noprint;
   create table new as 
   select id,location
   , month(crimedate) as month,count(crime) as crime_n
   from old
   group by id,location,CALCULATED month;
quit;

proc sgplot  data=new;
   series x=month y=crime_n /group=location;
run;

Результат:

Чтобы показать разные серии по типу преступления, вы можете использовать sgpanel:

proc sql noprint;
   create table new as 
   select id,crime,location, month(crimedate) as month,count(crime) as crime_n
   from old
   group by id,crime,location,CALCULATED month;
quit;

proc sgpanel  DATA=new;
   panelby location;
   series x=month y=crime_n /group=crime;
run;

Результат:

Еще один вариант выполнения этих данных:

proc sql noprint;
   create table new as 
   select id,crime,location, month(crimedate) as month,count(crime) as crime_n
   from old
   group by id,crime,location,CALCULATED month;
quit;

proc sgpanel  DATA=new;
   panelby crime;
   series x=month y=crime_n /group=location GROUPDISPLAY=cluster;
run;

Результат:

Конечно, вы можете указать эти графики, как вы хотите.

Чтобы, возможно, ответить на вопрос более прямо, VLINE или же HLINE графики будут обобщать данные для вас, аналогично proc freq а потом proc sgplot с участием series,

Используя тестовые данные Ричарда, вы увидите, что это в точности совпадает с графиком, который дает его PROC FREQ -> SERIES:

data have;
  do precinct = 1 to 10;
    do date = '01jan2018'd to '31dec2018'd;
      do seq = 1 to 20*ranuni(123);
        length crime $10 location $8;
        crime = scan('theft,assault,robbery,dnd', ceil(4*ranuni(123)));
        location = scan ('public,private', ceil(2*ranuni(123)));
        crime_dt = dhms(date,0,0,floor('24:00't*ranuni(123)));
        output;      
      end;
    end;
  end;
  drop date;
  format crime_dt datetime19.;
run;

proc sgplot data=have;
  vline crime_dt/group=location groupdisplay=cluster;
  format crime_dt dtmonyy7.;
run;

Другие вопросы по тегам