Работая с лабораторными данными, я хочу наложить на коробчатую диаграмму подмножество точек данных, сгруппированных по лечению и упорядоченных по временным точкам. Объединить все элементы вместе в SAS непросто и требует умного подхода, который я не могу придумать или найти сам :)
Прелесть желаемого графика в том, что он отображает 2 различных типа выбросов:
- Коробчатые диаграммы включают статистические выбросы - квадратные маркеры (1,5 IQR).
- Затем наложите маркеры для выбросов «нормального диапазона» - клиническое определение, специфичное для каждого лабораторного теста.
Это сложно при группировании данных (например, по обработке), а затем их блокировке или категоризации по другой переменной (например, момент времени). SAS внутренне определяет интервал коробчатых диаграмм, поэтому этот интервал трудно имитировать для наложенных маркеров данных нормального диапазона. Общее решение в этом направлении было бы ненадежным кладжем.
Ниже я продемонстрировал этот подход ручной имитации разделения групп для маркеров наложения - просто чтобы дать представление о намерениях. Как и ожидалось, выбросы нормального диапазона не совпадают с группами диаграмм. Кроме того, точки данных, которые соответствуют обоим критериям выбросов (статистическим и клиническим), отображаются как отдельные точки, а не как отдельные точки с наложенными маркерами. Мои аннотации зеленым цветом:
Есть ли простой и надежный способ указать SAS наложить сгруппированные точки данных на коробчатую диаграмму, сохраняя все согласованное, как задумано?
Вот код для воспроизведения этого промаха:
proc sql;
create table labstruct
( mygroup char(3) label='Treatment Group'
, myvisitnum num label='Visit number'
, myvisitname char(8) label='Visit name'
, labtestname char(8) label='Name of lab test'
, labseed num label='Lab measurement seed'
, lablow num label='Low end of normal range'
, labhigh num label='High end of normal range'
)
;
insert into labstruct
values('A', 1, 'Day 1', 'Test XYZ', 48, 40, 60)
values('A', 5, 'Week 1', 'Test XYZ', 50, 40, 60)
values('A', 10, 'Week 2', 'Test XYZ', 52, 40, 60)
values('B', 1, 'Day 1', 'Test XYZ', 52, 40, 60)
values('B', 5, 'Week 1', 'Test XYZ', 50, 40, 60)
values('B', 10, 'Week 2', 'Test XYZ', 48, 40, 60)
;
quit;
data labdata;
set labstruct;
* Put normal range outliers on 2nd axis, manually separate groups on 2nd axis *;
select (mygroup);
when ('A') scatternum = myvisitnum - 1;
when ('B') scatternum = myvisitnum + 1;
otherwise;
end;
* Make more obs from the seeds above *;
label labvalue = 'Lab measurement';
do repeat = 1 to 20;
labvalue = labseed + 6*rannor(3297);
* Scatter plot ONLY normal range outliers *;
if labvalue < lablow or labvalue > labhigh
then scattervalue = labvalue;
else scattervalue = .;
output;
end;
drop repeat labseed;
run;
proc sgplot data=labdata;
block x=myvisitnum block=myvisitname /
nofill
lineattrs=(color=lightgray);
vbox labvalue /
category=myvisitnum
group=mygroup
outlierattrs=(symbol=square);
scatter x=scatternum y=scattervalue /
group=mygroup
x2axis
jitter;
x2axis display=none;
keylegend / position=bottom type=marker;
run;