#sas
#sas
Вопрос:
У меня есть результаты тестов многих студентов за 8 разных лет. Я хочу сохранить только максимальный общий балл каждого учащегося, но затем также сохранить всю информацию, связанную с учебным годом, для этого результата теста (то есть все столбцы того же года, в котором учащийся получил наивысший общий балл).
Пример наборов данных, которые у меня есть:
%macro score;
%do year = 2010 %to 2018;
data student_amp;year.;
do id=1 to 10;
english=25*rand('uniform');
math=25*rand('uniform');
sciences=25*rand('uniform');
history=25*rand('uniform');
total_score=sum(english, math, sciences, history);
output;
end;
%end;
run;
%mend;
%score;
В моем ожидаемом результате я хотел бы сохранить максимальное значение total_score для каждого учащегося, а также иметь другие столбцы, связанные с этим общим счетом. Если возможно, я также хотел бы получить информацию о годе, в котором учащийся получил максимальное значение total_score. Примером ожидаемого результата может быть:
DATA want;
INPUT id total_score english math sciences history year;
CARDS;
1 75.4 15.4 20 20 20 2017
2 63.8 20 13.8 10 20 2016
3 48 10 10 18 10 2018
4 52 12 10 10 20 2016
5 69.5 20 19.5 20 10 2013
6 85 20.5 20.5 21 23 2011
7 41 5 12 14 10 2010
8 55.3 15 20.3 10 10 2012
9 51.5 10 20 10 11.5 2013
10 48.9 12.9 16 10 10 2015
;
RUN;
Я пытался работать с процедурой SAS UPDATE
. Но он просто получает самое последнее значение для каждого учащегося. Мне нужен максимальный общий балл. Кроме того, в рамках обновления мне нужно обновлять две таблицы одновременно. Я хотел бы сравнить все таблицы одновременно. Итак, эта стратегия, которую я пытаюсь, не работает:
data want;
update score_2010 score_2011;
by id;
Спасибо всем, кто может предоставить информацию.
Ответ №1:
Легче получить то, что вы хотите, если у вас есть только один продольный набор данных со всей исходной информацией ваших студентов. Это также имеет больше смысла, поскольку вы сравниваете студентов разных лет.
Чтобы построить продольный набор данных, вам сначала нужно будет вставить переменную, информирующую год каждого из ваших исходных наборов данных. Например, с:
%macro score;
%do year = 2010 %to 2018;
data student_amp;year.;
do id=1 to 10;
english=25*rand('uniform');
math=25*rand('uniform');
sciences=25*rand('uniform');
history=25*rand('uniform');
total_score=sum(english, math, sciences, history);
year=amp;year.;
output;
end;
%end;
run;
%mend;
%score;
После включения года вы можете получить продольный набор данных с:
data student_allyears;
set student_201:;
run;
Наконец, вы можете получить то, что хотите, с помощью proc sql, в котором вы выбираете максимальное значение «total_score», сгруппированное по «id»:
proc sql;
create table want as
select distinct *
from student_allyears
group by id
having total_score=max(total_score);
Комментарии:
1. Хорошо, Ричард пришел первым и сделал лучше (короче), чем я. Это в основном то же самое. Но, возможно, мой ответ все же будет полезен.
Ответ №2:
Создайте представление, которое объединяет отдельные наборы данных, и выполните его обработку.
Пример (SQL select
, group by
, и having
)
data scores / view=scores;
length year $4;
set work.student_2010-work.student_2018 indsname=dsname;
year = scan(dsname,-1,'_');
run;
proc sql;
create table want as
select * from scores
group by id
having total_score=max(total_score)
;
Пример обработки цикла DOW
Складывайте данные, чтобы представление было доступно для обработки BY ID
. Первые циклы DOW вычисляют, какая запись имеет максимальный общий балл по группе, а вторая выбирает запись в группе для ВЫВОДА
data scores_by_id / view=scores_by_id;
set work.student_2010-work.student_2018 indsname=dsname;
by id;
year = scan(dsname,-1,'_');
run;
data want;
* compute which record in group has max measure;
do _n_ = 1 by 1 until (last.id);
set scores_by_id;
by id;
if total_score > _max then do;
_max = total_score;
_max_at_n = _n_;
end;
end;
* output entire record having the max measure;
do _n_ = 1 to _n_;
set scores_by_id;
if _n_ = _max_at_n then OUTPUT;
end;
drop _max:;
run;