SAS Второе наименьшее значение
Следующий код, созданный с помощью задачи "Сводная статистика" из SAS Enterprise Guide, находит минимум каждого столбца таблицы.
Как я могу найти второе наименьшее значение? Я попытался заменить MIN на SMALLEST(2), но не работает.
Спасибо.
TITLE;
TITLE1 "Summary Statistics";
TITLE2 "Results";
FOOTNOTE;
FOOTNOTE1 "Generated by the SAS System (&_SASSERVERNAME, &SYSSCPL) on
%TRIM (%QSYSFUNC(DATE(), NLDATE20.)) at
%TRIM(%SYSFUNC(TIME(), TIMEAMPM12.))";
PROC MEANS DATA=WORK.SORTTempTableSorted
NOPRINT
CHARTYPE
MIN NONOBS ;
VAR A B C;
OUTPUT OUT=WORK.MEANSummaryStats(LABEL="Summary Statistics for
WORK.QUERY_FOR_TRNSTRANSPOSEDPD__0001")
MIN()=
/ AUTONAME AUTOLABEL INHERIT
;
БЕЖАТЬ;
5 ответов
Использование таблицы ExtremeValue из PROC UNIVARIATE.
ods select none;
ods output ExtremeValues=ExtremeValues(where=(loworder=2) drop=high:);
proc univariate data=sashelp.class NEXTRVAL=2;
run;
ods select all;
proc print;
run;
Сортировать значения в порядке возрастания. Удалить первое значение. Это будет минимальное значение. Теперь значение, оставленное на первой позиции, является вашим вторым минимумом.
Решение шага данных, которое должно работать для любого количества столбцов, не сталкиваясь с ограничениями макросов:
proc sql noprint;
select count(*) into :NUM_COUNT from dictionary.columns
where LIBNAME='SASHELP' and MEMNAME = 'CLASS' and TYPE = 'num';
quit;
data class_min2;
do until(eof);
set sashelp.class end = eof;
array min2[&NUM_COUNT,2] _temporary_;
array nums[*] _numeric_;
do _n_ = 1 to &NUM_COUNT;
min2[_n_,1] = min(min2[_n_,1],nums[_n_]);
if min2[_n_,1] < nums[_n_] then min2[_n_,2] = min(nums[_n_],min2[_n_,2]);
end;
end;
do _iorc_ = 1 to 2;
do _n_ = 1 to &NUM_COUNT;
nums[_n_] = min2[_n_,_iorc_];
end;
output;
end;
keep _NUMERIC_;
run;
Это выводит два наименьших отличных значения каждой числовой переменной, без транспонирования данных так же, как proc univariate
делает. Вы можете легко допустить дублирование минимальных значений с небольшой настройкой.
Я предполагаю, что вы заинтересованы во всех числовых столбцах. Если длина макропеременной IFLIST превышает 64 КБ из-за количества числовых переменных и длины их имен, этот код завершится ошибкой. Это должно работать для всех достаточно узких наборов данных.
НЕПРОВЕРЕННЫЙ КОД
Мы получаем список переменных в вашем наборе данных.
PROC CONTENTS DATA=SORTTempTableSorted OUT=md NOPRINT ;
RUN ;
Мы используем этот список для создания выражений и выражений.
IFLIST - это блок операторов для хранения минимального значения fieldname в fieldname_1 и второго наименьшего в fieldname_2. Если сравнение LT, то мы сохраняем различные значения, не обязательно статистику заказа. Если сравнение - LE, и есть несколько наблюдений с минимальным значением, fieldname_1 и fieldname_2 будут равны друг другу. Я предполагаю, что вы хотите разные значения.
MAXLIST - это выражение, которое преобразуется в наибольшее числовое значение в наборе данных:)
MINLIST и MINLIST2 созданы для использования в операторах RETAIN и KEEP.
PROC SQL STIMER NOPRINT EXEC ;
SELECT 'IF ' || name || ' LT ' || name '_1 THEN DO;' ||
name || '_2=' || name || '_1;' ||
name || '_1=' || name || ';END;ELSE IF ' ||
name || ' LT ' || name || '_2 THEN ' ||
name || '_2=' || name,
'MAX(' || name || ')',
name || '_1',
name || '_2'
INTO :iflist SEPARATED BY '; ',
:maxlist SEPARATED BY '<>'
:minlist SEPARATED BY ' ',
:min2list SEPARATED BY ' '
FROM md
WHERE type EQ 1
;
Теперь мы получаем наибольшее числовое значение из набора данных:
SELECT &maxlist
INTO :maxval
FROM SORTTempTableSorted
;
QUIT ;
Сейчас мы делаем работу. Опция END устанавливает "eof" в 1 для последнего наблюдения, и это единственный раз, когда мы хотим записать запись в выходной набор данных.
DATA min2 ;
SET SORTTempTableSorted END=eof;
RETAIN &minlist &min2list &maxval;
KEEP &minlist &min2list ;
&iflist ;
IF eof THEN
OUTPUT ;
RUN ;
Я не думаю, что есть какой-либо способ сделать это с помощью средств. Есть способы, использующие множество других процедур. Процедура Univariate выделяет один метод, использующий экстремальные наблюдения.
https://support.sas.com/documentation/cdl/en/procstat/63104/HTML/default/viewer.htm
title 'Extreme Blood Pressure Observations';
ods select ExtremeObs;
proc univariate data=BPressure;
var Systolic Diastolic;
id PatientID;
run;
proc print data=ExtremeObs;
run;