2015-10-06 2 views
0

Мне нужно предоставить отчет группе людей, суммирующих информацию каждого человека, но только показывая имя человека, к которому каждый отчет собирается. Что у меня есть:Необходимо скрыть некоторые поля для одной переменной, SAS/SQL

Алиса 4 15% 8 20%
Боб 8 30% 6 15%
Carol 4 15% 8 20%
Dave 4 15% 8 20%
Erin 4 15% 8 20%

Что я хочу:

Резюме Алиса
Алиса 4 15% 8 20%
Person2 8 30% 6 15%
Person3 4 15% 8 20%
Person4 4 15% 8 20%
Person5 4 15% 8 20%

Резюме Боба
Person1 4 15% 8 20%
Боб 8 30% 6 15%
Person3 4 15% 8 20%
Person4 4 15% 8 20%
Person5 4 15% 8 20%

и так далее.

Я попробовал несколько вещей, отказались от наличия номер после человека, и моя последняя попытка следующим образом:

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; 

Я знаю, что, вероятно, искаженное выше, но на самом деле нужно, чтобы выяснить, как для этого используйте SAS/SQL либо в proc sql, либо в шагах данных.

Спасибо!

ответ

0

Не уверен, что вы точно попытаться сделать в вашей макро и без точно зная, что все это происходит не так с вашим результатом, я могу обнаружить 3 ошибки в коде:

1.

data person; 

в вашем цикле, каждый раз, когда вы выполняете цикл, вы перезаписываете данные набора данных. В следующем цикле вы снова получите доступ к перезаписанному набору данных. Поэтому в конце у вас есть только один набор данных, и потому, что вы перезаписали его каждый раз, когда в качестве имен остался только personx. Поэтому вам нужно написать data person&j;, чтобы получить единый набор данных для каждого человека.

2.

set person; 

Что такое набор данных людей? вы не определили его раньше в своем примере. Насколько я понимаю, что вы пытаетесь сделать, вы должны использовать здесь set have;.

3.

вы забыли перезаписать Name

if Name="&&Person&j" then 
name ="&&Person&j"; 
else 
name ="&Person"; 

или простой вариант:

if Name ne "&&Person&j" then 
    name ="&Person"; 

4.

не ошибка, но вы должны использовать data _null_; вместо data people;, потому что вы используя этот datastep только для создания некоторых макровирусов и никогда больше не использовать вывод, поэтому нет необходимости создавать новый набор данных здесь. И прекратите осле datastep устарела ...


Edit:

я тестировал сегодня, этот код работает определенно для меня, если вы все равно получите ошибку я думаю, вы есть опечатка или что-то неправильно в среда:

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; 

Результат:

enter image description here

+0

Так что код в порядке. Как получить результаты, которые мне нужны? Я очень застрял здесь. Как уже упоминалось, я также буду выводить каждый набор данных человеком. –

+0

Что вы получаете как результат, когда делаете изменения, о которых я упоминал? Пока ваш код выглядит неплохо, только некоторые логические ошибки – kl78

+0

Я возвращаю исходную таблицу «Want». Кажется, что независимо от того, что я делаю, я возвращаю этот стол. –

0

У меня частично есть решение, используя запрос объединения в proc sql, который содержит подзапросы для достижения имени и номера анонимных лиц.

Но, как вы видите, каждый человек вводится вручную в каждый запрос на выбор. Вам не хотелось бы этого делать, если в вашем наборе данных было 200 человек вместо 5, которые вы показываете в примере. Одна из возможностей заключается в том, чтобы запускать запросы на вставку, отражающие запросы выбора объединения:

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; 

Данные выходного набора. Отсюда экспортировать индивидуальный отчет каждого человека последним ReportToWhom колонке

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 
... 

Одним из возможных решений является использование каскадного запрос вставки 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; 

А затем передать строку в proc sql макро :

%macro runsql; 
    proc sql; 
     &query; 
    quit; 
%mend runsql; 

%runsql; 

в R, я мог бы сделать это в секундах с петлей paste/for/apply функции, но синтаксис SAS - это другой мир!

+0

Хотя похоже, что это сработает, ответ kl78 - именно то, что я искал !! Спасибо, что помогли! –

Смежные вопросы