I think you have an unfortunate nonnormalized data structure that makes the task harder.
If I take
data grades;
input id grade1 grade2 grade3 grade4;
datalines;
1105 1 2 3 4
1106 2 2 2 2
1107 3 3 4 6
;
run;
and flip it to a normalized structure like
proc sql;
create table grades_normalized as
select id as id, 'assignment1' as assignment, grade1 as grade
from grades
union
select id, 'assignment2', grade2
from grades
union
select id, 'assignment3', grade3
from grades
union
select id, 'assignment4', grade4
from grades;
quit;
I get a table that looks like
Obs id assignment grade 1 1105 assignment1 1 2 1105 assignment2 2 3 1105 assignment3 3 4 1105 assignment4 4 5 1106 assignment1 2 6 1106 assignment2 2 7 1106 assignment3 2 8 1106 assignment4 2 9 1107 assignment1 3 10 1107 assignment2 3 11 1107 assignment3 4 12 1107 assignment4 6
With that structure, I can sort (not needed for this data, but you never know) and trim.
proc sort data= grades_normalized;
by id grade;
run;
data trimmed_grades;
set grades_normalized;
by id;
if first.id then delete;
if last.id then delete;
run;
then summarize
proc sql;
create table grade_report as
select id as id, sum(grade) as grade_total
from trimmed_grades
group by id
order by id;
quit;
and end up with
grade_ Obs id total 1 1105 5 2 1106 4 3 1107 7
Now one of the experts around here will post a solution that does this all in the data step or with a macro or something but they haven't replied so you are stuck with me.
EDIT:
Did I not say somebody better than me would come along and do it in the data step?
data grades;
input id 4. g1-g13;
datalines;
1105 8 7 5 8 3 7 7 8 8 8 8 8 6
1294 8 8 8 7 5 7 8 8 8 8 5 8 2
2009 8 6 3 8 4 6 7 7 8 7 0 4 7
;
run;
data want;
set grades;
total = sum( of g1-g13);
trim_total = total - max(of g1-g13) - min(of g1-g13);
run;
... View more