需要为一个变量SAS/SQL隐藏一些字段
我需要给一群人做一份报告,总结每个人的信息,但只透露每个报告将要报告的人的姓名。 我得到的是: 爱丽丝4 15%8 20% 鲍勃8 30%6 15%需要为一个变量SAS/SQL隐藏一些字段,sql,loops,sas,data-hiding,anonymity,Sql,Loops,Sas,Data Hiding,Anonymity,我需要给一群人做一份报告,总结每个人的信息,但只透露每个报告将要报告的人的姓名。 我得到的是: 爱丽丝4 15%8 20% 鲍勃8 30%6 15% 卡罗尔4 15%8 20% 戴夫4 15%8 20% 艾琳4 15%8 20% 我想要的是: 爱丽丝的总结 爱丽丝4 15%8 20% 个人2 8 30%6 15% 个人3 4 15%8 20% 人员4 15%8 20% 人员5 4 15%8 20% 鲍勃的总结 人员1 4 15%8 20% 鲍勃8 30%6 15% 个人3 4 15%8 20%
卡罗尔4 15%8 20%
戴夫4 15%8 20%
艾琳4 15%8 20% 我想要的是: 爱丽丝的总结
爱丽丝4 15%8 20% 个人2 8 30%6 15%
个人3 4 15%8 20%
人员4 15%8 20%
人员5 4 15%8 20% 鲍勃的总结
人员1 4 15%8 20%
鲍勃8 30%6 15%
个人3 4 15%8 20%
人员4 15%8 20%
人员5 4 15%8 20% 等等 我已经尝试过几种方法,放弃了在person后面加数字,我最近的尝试如下:
proc sql;
create table Distinct_People
as select distinct(Name)
from have;
quit;
data People;
set Distinct_People end=no_more;
call symputx('Person'||left(_n_), Name);
if no_more then call symputx('NumPeople', _n_);
run;
quit;
%macro Loop;
%do j=1 %to &NumPeople;
%let Person=Person&j;
data want;
set have;
if Name="&&Person&j" then "&&Person&j";
else "Person";
run;
%end;
%mend Loop;
%Loop;
我知道我可能已经弄糟了上面的内容,但我真的需要弄清楚如何在procsql或数据步骤中使用SAS/SQL来实现这一点
谢谢大家! 我不知道您在宏中到底想做什么,也不知道您的结果到底出了什么问题,我可以在代码中发现3个错误: 一, 在循环中,每次执行循环时,都会覆盖数据集。在下一个循环中,您将再次访问覆盖的数据集。所以最后你只有一个数据集,因为每次只剩下人名时你都会覆盖它。所以你必须写
数据人&j
为每个人获取一个数据集
二,
人是什么?您以前没有在示例中定义它。据我所知,您必须使用set have代码>这里
三,
您忘了覆盖名称
if Name="&&Person&j" then
name ="&&Person&j";
else
name ="&Person";
或更简单的版本:
if Name ne "&&Person&j" then
name ="&Person";
四,
不是错误,但您应该使用data\u null\u代码>而不是数据人代码>,因为您使用此数据步骤只是为了生成一些宏变量,并且不再使用输出,因此无需在此创建新的数据集。并且在数据步骤过时后退出
编辑:
我今天进行了测试,这段代码对我来说绝对有效,如果您仍然出现错误,我猜您可能是输入错误,或者您的环境出了问题:
data have;
input name $ nr1 nr2 $ nr3 n4 $;
datalines;
Alice 4 15% 8 20%
Bob 8 30% 6 15%
Carol 4 15% 8 20%
Dave 4 15% 8 20%
Erin 4 15% 8 20%
;
run;
proc sql;
create table Distinct_People
as select distinct(Name)
from have;
quit;
data _null_;
set Distinct_People end=no_more;
call symputx('Person'||left(_n_), Name);
if no_more then call symputx('NumPeople', _n_);
run;
quit;
%macro Loop;
%do j=1 %to &NumPeople;
data want&j;
set have;
if Name ne "&&Person&j" then name = cat("Person",_n_);
run;
%end;
%do j=1 %to &NumPeople;
proc print data=want&j;
title1 " &&Person&j.'s Summary";
run;
%end;
%mend Loop;
%Loop;
结果:
我在proc sql
中有一个使用联合查询的部分解决方案,其中包含子查询以获得匿名人员的姓名和号码
但正如您所注意到的,每个人都是手动输入到每个select查询中的。您可能不愿意为数据集中的200人而不是示例中显示的5人这样做。一种可能是运行insert查询,以镜像union的select查询:
proc sql;
create table AnonymousReport As
SELECT CASE WHEN t1.name = 'Alice' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Alice' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Bob' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Bob' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Carol' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Carol' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Dave' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Dave' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Erin' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Erin' As ReportToWhom
FROM have t1;
quit;
一种可能的解决方案是跨数据集的所有行使用串联的insert SQL查询:
data concat;
set have;
length reptAll $3200;
by name;
retain reptAll;
if first.name then reptAll = "";
unionSQL = "INSERT INTO AnonymousReport (RptName, Col1Number, Col1Pct, Col2Number, Col2Pct, ReportToWhom)
SELECT CASE WHEN t1.name = '" || name || "' THEN t1.name
ELSE CATS('Person', (SELECT count(name) + 1 From have t2
WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, '" || name || "' As ReportToWhom
FROM have t1";
reptAll = catx('; ', reptAll, unionSQL) ;
call symput('query', reptAll);
if last.name then output;
run;
在R中,我可以用它的粘贴
/for
循环/应用
函数在几秒钟内完成这项工作,但SAS语法是另一个世界 那么代码就太离谱了。如何获得所需的结果?我被困在这里了。如前所述,我还将按个人输出每组数据。当您只做我提到的更改时,您会得到什么结果?到目前为止,您的代码看起来不错,只是一些逻辑错误,我得到了原始表“Want”。似乎无论我做什么,我都会把那张表拿回来。@s.Cross:发现另一个错误,将其添加到我的原始答案中(第3点)。但在代码中,如果不使用第1点,您仍然只能得到一个数据集,其中包含max j的结果。如果I include name=,返回错误180,表示name不符合顺序,而这看起来可以正常工作,kl78的回答正是我要找的!!谢谢你的帮助!
proc sql;
create table AnonymousReport As
SELECT CASE WHEN t1.name = 'Alice' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Alice' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Bob' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Bob' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Carol' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Carol' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Dave' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Dave' As ReportToWhom
FROM have t1
UNION ALL
SELECT CASE WHEN t1.name = 'Erin' THEN t1.name ELSE CATS('Person',
(SELECT count(name) + 1 From have t2
WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Erin' As ReportToWhom
FROM have t1;
quit;
RptName Col1Number Col1Pct Col2Number Col2Pct ReportToWhom
Alice 4 15% 8 20% Alice
Person2 8 30% 6 15% Alice
Person3 4 15% 8 20% Alice
Person4 4 15% 8 20% Alice
Person5 4 15% 8 20% Alice
Person1 4 15% 8 20% Bob
Bob 8 30% 6 15% Bob
Person3 4 15% 8 20% Bob
Person4 4 15% 8 20% Bob
Person5 4 15% 8 20% Bob
...
data concat;
set have;
length reptAll $3200;
by name;
retain reptAll;
if first.name then reptAll = "";
unionSQL = "INSERT INTO AnonymousReport (RptName, Col1Number, Col1Pct, Col2Number, Col2Pct, ReportToWhom)
SELECT CASE WHEN t1.name = '" || name || "' THEN t1.name
ELSE CATS('Person', (SELECT count(name) + 1 From have t2
WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName,
t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, '" || name || "' As ReportToWhom
FROM have t1";
reptAll = catx('; ', reptAll, unionSQL) ;
call symput('query', reptAll);
if last.name then output;
run;
%macro runsql;
proc sql;
&query;
quit;
%mend runsql;
%runsql;