sas 计数不同组合的数量
sas count number of different combinations
我有一个数据集,其中包含有关某个机构的学生教育信息。
我想知道他们参加过多少种不同的学习项目组合。我有硕士和学士级别的信息,我想统计每个教育级别(硕士、学士)的不同学习课程的数量。
例如 person1 可以有:
Bachelor:
- study1
- study2
- study3
- study3
Master:
- studyA
- studyA
然后我想要学士级别的3个学习项目(study3不应该算两次),硕士级别的1个。
每个学习计划都有自己的行 - 所以在数据集中 person1 有 6 行。
我希望每人一行告诉每个教育级别的学习课程数量:
person number_bachelor number_master
person1 3 1
....etc...
我试过这个:
proc sql;
create table new as
select distinct personid, name,
count(study) as number_of_bach
from old
group by personid, edu_level, study;
quit;
但它并没有给我想要的东西。
这给了我两行 person1,变量 "number_of_bach".
中的值为 1 和 2
如何编辑此代码以获得我想要的结果?
这是你想要的吗?
DATA old;
INPUT personid edu_level $ study $;
DATALINES;
1 bachelor study1
1 bachelor study2
1 bachelor study3
1 bachelor study3
1 master studyA
1 master studyA
1 master studyB
;
PROC SQL;
CREATE TABLE new AS
SELECT personid, edu_level, COUNT (DISTINCT study) AS num_bach
FROM OLD
GROUP BY personid, edu_level;
QUIT;
列 study
是您查询中所谓的聚合列(因为 COUNT
是一个聚合函数),因此不应包含在 GROUP BY
-子句(否则您的查询也将按 'study' 分组并且计数将始终为 1.
如果你想每人一个,然后添加一个 PROC TRANSPOSE
:
PROC transpose IN = new OUT = new2;
BY personid;
ID edu_level;
RUN;
(您也可以使用子查询和连接而不是转置创建更复杂的查询,只要您没有数百万行,TRANSPOSE
的开销无关紧要)
为了完整起见,这里有一个 SQL-only 解决方案来解决你的问题:
PROC SQL;
CREATE TABLE new AS
SELECT p.personid, b.num_bachelors, m.num_masters
/* Select unique personids */
FROM (SELECT DISTINCT personid
FROM old) AS p
/* Count number of bachelor-level courses */
LEFT JOIN (SELECT personid,
COUNT(DISTINCT study) AS num_bachelors
FROM old WHERE edu_level = 'bachelor'
GROUP BY personid) AS b on p.personid = b.personid
/* Count number of master-level courses */
LEFT JOIN (SELECT personid,
COUNT(DISTINCT study) AS num_masters
FROM old WHERE edu_level = 'master'
GROUP BY personid) AS m on p.personid = m.personid;
QUIT;
代码:
data education;
input person $ level $ program $;
datalines;
person1 bachelor study1
person1 bachelor study2
person1 bachelor study3
person1 bachelor study3
person1 master study1
person2 bachelor study1
person2 master study2
person2 master study1
;
run;
proc sort data = education nodupkey;
by person level program;
run;
proc sql;
select person,
sum(case when level eq 'bachelor' then 1 else 0 end) as num_bachelors,
sum(case when level eq 'bachelor' then 1 else 0 end) as num_masters
from education
group by person;
quit;
工作:在这里,SORT 程序将消除重复记录(如果有)。然后 SQL 过程只能用于生成学士级别的程序的人明智计数以及硕士级别的程序计数。
输出:
person num_bachelors num_masters
person1 3 1
person2 1 2
我有一个数据集,其中包含有关某个机构的学生教育信息。 我想知道他们参加过多少种不同的学习项目组合。我有硕士和学士级别的信息,我想统计每个教育级别(硕士、学士)的不同学习课程的数量。
例如 person1 可以有:
Bachelor:
- study1
- study2
- study3
- study3
Master:
- studyA
- studyA
然后我想要学士级别的3个学习项目(study3不应该算两次),硕士级别的1个。 每个学习计划都有自己的行 - 所以在数据集中 person1 有 6 行。 我希望每人一行告诉每个教育级别的学习课程数量:
person number_bachelor number_master
person1 3 1
....etc...
我试过这个:
proc sql;
create table new as
select distinct personid, name,
count(study) as number_of_bach
from old
group by personid, edu_level, study;
quit;
但它并没有给我想要的东西。 这给了我两行 person1,变量 "number_of_bach".
中的值为 1 和 2如何编辑此代码以获得我想要的结果?
这是你想要的吗?
DATA old;
INPUT personid edu_level $ study $;
DATALINES;
1 bachelor study1
1 bachelor study2
1 bachelor study3
1 bachelor study3
1 master studyA
1 master studyA
1 master studyB
;
PROC SQL;
CREATE TABLE new AS
SELECT personid, edu_level, COUNT (DISTINCT study) AS num_bach
FROM OLD
GROUP BY personid, edu_level;
QUIT;
列 study
是您查询中所谓的聚合列(因为 COUNT
是一个聚合函数),因此不应包含在 GROUP BY
-子句(否则您的查询也将按 'study' 分组并且计数将始终为 1.
如果你想每人一个,然后添加一个 PROC TRANSPOSE
:
PROC transpose IN = new OUT = new2;
BY personid;
ID edu_level;
RUN;
(您也可以使用子查询和连接而不是转置创建更复杂的查询,只要您没有数百万行,TRANSPOSE
的开销无关紧要)
为了完整起见,这里有一个 SQL-only 解决方案来解决你的问题:
PROC SQL;
CREATE TABLE new AS
SELECT p.personid, b.num_bachelors, m.num_masters
/* Select unique personids */
FROM (SELECT DISTINCT personid
FROM old) AS p
/* Count number of bachelor-level courses */
LEFT JOIN (SELECT personid,
COUNT(DISTINCT study) AS num_bachelors
FROM old WHERE edu_level = 'bachelor'
GROUP BY personid) AS b on p.personid = b.personid
/* Count number of master-level courses */
LEFT JOIN (SELECT personid,
COUNT(DISTINCT study) AS num_masters
FROM old WHERE edu_level = 'master'
GROUP BY personid) AS m on p.personid = m.personid;
QUIT;
代码:
data education;
input person $ level $ program $;
datalines;
person1 bachelor study1
person1 bachelor study2
person1 bachelor study3
person1 bachelor study3
person1 master study1
person2 bachelor study1
person2 master study2
person2 master study1
;
run;
proc sort data = education nodupkey;
by person level program;
run;
proc sql;
select person,
sum(case when level eq 'bachelor' then 1 else 0 end) as num_bachelors,
sum(case when level eq 'bachelor' then 1 else 0 end) as num_masters
from education
group by person;
quit;
工作:在这里,SORT 程序将消除重复记录(如果有)。然后 SQL 过程只能用于生成学士级别的程序的人明智计数以及硕士级别的程序计数。
输出:
person num_bachelors num_masters
person1 3 1
person2 1 2