BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Jonate_H
Quartz | Level 8

I tried to calculate median of age and weight by city and by sex, the expected result is showed in the image. I wrote something like

data want;

set have;

by sex city;

median_age=median(age);

median_weight=median(weight);

run;

That doesn't work, looks like median() can't calculate numbers in a column, it works for numbers in the same row I think?

Thank you for your help.

have.jpg

1 ACCEPTED SOLUTION

Accepted Solutions
Reeza
Super User

Go "old school" - use proc means and merge the results back in.

You can use the ways/types to control the different levels of output required.

Here's an example using SEX and WAYS 1 to get only the output by Sex levels.

proc means data=sashelp.class noprint;

class sex;

ways 1;

var weight age;

output out=med_vars median(weight)=med_weight median(age)=med_age;

run;

proc sql;

create table want as

select a.*, b.med_weight, b.med_age

from sashelp.class as a

left join med_vars as b

on a.sex=b.sex;

quit;


And an example using WAYS 2 with the CARS dataset


proc means data=sashelp.cars noprint;

class make type;

ways 2;

var mpg_city mpg_highway;

output out=med_vars2 median(mpg_city)=med_city median(mpg_highway)=med_highway;

run;

proc sql;

create table want as

select a.*, b.med_city, b.med_highway

from sashelp.cars as a

left join med_vars2 as b

on a.make=b.make

and a.type=b.type;

quit;

View solution in original post

7 REPLIES 7
Haikuo
Onyx | Level 15

/*If you have SAS 9.4, it is easy*/

proc sql;

     create table want as

           select *, median(age) as median_age, median(weight) as median_wt

                from sashelp.class;

quit;

/*If not, it will take some twists*/

data _null_;

     call symputx('nobs',nobs);

     stop;

     set sashelp.class nobs=nobs;

run;

data want_no94;

     do _n_=1 by 1 until (last);

           set sashelp.class (keep=age weight)end=last;

           array _age(&nobs) _temporary_;

           array _wt(&nobs) _temporary_;

           _age(_n_)=age;

           _wt(_n_)=weight;

     end;

     do _n_=1 by 1 until (last1);

           set sashelp.class end=last1;

           retain median_age median_wt;

           if _n_=1 then

                do;

                     median_age=median(of _age(*));

                     median_wt=median(of _wt(*));

                end;

           output;

     end;

run;

Jonate_H
Quartz | Level 8

Thanks a lot for your reply! I have 9.3 version, so it is kind of headache.

I found that with your code, the resulted median is the median for the age or weight of whole data set.

So, how can I calculate the median by sex and by other variables at the same time if necessary? thanks!

Reeza
Super User

Go "old school" - use proc means and merge the results back in.

You can use the ways/types to control the different levels of output required.

Here's an example using SEX and WAYS 1 to get only the output by Sex levels.

proc means data=sashelp.class noprint;

class sex;

ways 1;

var weight age;

output out=med_vars median(weight)=med_weight median(age)=med_age;

run;

proc sql;

create table want as

select a.*, b.med_weight, b.med_age

from sashelp.class as a

left join med_vars as b

on a.sex=b.sex;

quit;


And an example using WAYS 2 with the CARS dataset


proc means data=sashelp.cars noprint;

class make type;

ways 2;

var mpg_city mpg_highway;

output out=med_vars2 median(mpg_city)=med_city median(mpg_highway)=med_highway;

run;

proc sql;

create table want as

select a.*, b.med_city, b.med_highway

from sashelp.cars as a

left join med_vars2 as b

on a.make=b.make

and a.type=b.type;

quit;

Jonate_H
Quartz | Level 8

Thank you, Reeza! that works well.

Haikuo
Onyx | Level 15

Sorry, I wasn't reading your question thoroughly enough. Here is the modified code. Well, if you have 9.3, then has already offered better options:

/*If you have SAS 9.4, it is easy*/

proc sql;

create table want as

           select *, median(age) as median_age, median(weight) as median_wt

                from sashelp.class

group by sex;

quit;

/*If not, it will take some twists*/

proc sql;

select max(ct) into :dim trimmed from

(select count(*) as ct from sashelp.class group by sex)

;quit;

proc sort data=sashelp.class out=class;

by sex;

run;

data want_no94;

do _n_=1 by 1 until (last.sex);

           set class end=last;

              by sex;

           array _age(&dim) _temporary_;

           array _wt(&dim) _temporary_;

           _age(_n_)=age;

           _wt(_n_)=weight;

end;

do _n_=1 by 1 until (last.sex);

           set class end=last1;

              by sex;

           retain median_age median_wt;

           if _n_=1 then

                do;

                     median_age=median(of _age(*));

                     median_wt=median(of _wt(*));

                end;

           output;

end;

run;

Jonate_H
Quartz | Level 8

Thanks! that's also very helpful.

jfcubells
Calcite | Level 5

Hi. It was really helpful this query.

Now I'm trying to do something similar, but calculating interquartile range instead of median. Is there any way to do that?

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 34973 views
  • 5 likes
  • 4 in conversation