2013-02-19 136 views
0

我有一個SAS數據集,看起來像這樣:拆分SAS數據集

id | dept | ... 
1 A 
2 A 
3 A 
4 A 
5 A 
6 A 
7 A 
8 A 
9 B 
10 B 
11 B 
12 B 
13 B 

每個觀察代表一個人。

我想將數據集分成「團隊」數據集,每個數據集最多可以有3個觀察值。

對於上述示例,這意味着要爲部門A創建3個數據集(其中2個數據集包含3個觀察值,第3個數據集包含2個觀察值)。以及B部分的2個數據集(1個包含3個觀測值,另一個包含2個觀測值)。

像這樣:

第一個數據集(deptA1):

id | dept | ... 
1 A 
2 A 
3 A 

第二個數據集(deptA2)

id | dept | ... 
4 A 
5 A 
6 A 

第三數據集(deptA3)

id | dept | ... 
7 A 
8 A 

四集(deptB1)

id | dept | ... 
9 B 
10 B 
11 B 

第五數據集(deptB2)

id | dept | ... 
12 B 
13 B 

我使用的完整數據集包含成千上萬的觀察與超過50個科指南我可以計算出每個部門需要多少個數據集,我認爲一個宏是最好的方法,因爲所需數據集的數量是動態的。但我無法弄清楚創建數據集的邏輯,以便它們最多有3個觀察值。任何幫助讚賞。

+0

爲什麼你想要像這樣拆分數據集?一般來說,將數據保存爲許多數據集是很糟糕的做法 - 這很難處理,必須運行50次,並且必須對所有50個數據集進行準確的更改。如果你想由團隊做一些分析,SAS有一個非常強大的概念,稱爲「BY」語句 - 只需創建一個新變量,爲其分配團隊價值,然後任何分析都可以由團隊完成; ,並且就像您有50個不同的數據集一樣 - 只是在一個物理數據集中。例如,請參閱http://goo.gl/tfwcr。 – Joe 2013-02-19 15:55:16

回答

1

另一個版本。 與DavB版本相比,它只處理一次輸入數據,並將其拆分爲單個datastep中的多個表格。 另外,如果需要更復雜的拆分規則,則可以在datastep視圖WORK.SOURCE_PREP中實施。

data WORK.SOURCE; 
infile cards; 
length ID 8 dept $1; 
input ID dept; 
cards; 
1 A 
2 A 
3 A 
4 A 
5 A 
6 A 
7 A 
8 A 
9 B 
10 B 
11 B 
12 B 
13 B 
14 C 
15 C 
16 C 
17 C 
18 C 
19 C 
20 C 
; 
run; 

proc sort data=WORK.SOURCE; 
by dept ID; 
run; 

data WORK.SOURCE_PREP/view=WORK.SOURCE_PREP; 
set WORK.SOURCE; 
by dept; 
length table_name $32; 

if first.dept then do; 
    count = 1; 
    table = 1; 
end; 
else count + 1; 

if count > 3 then do; 
    count = 1; 
    table + 1; 
end; 
/* variable TABLE_NAME to hold table name */ 
TABLE_NAME = catt('WORK.', dept, put(table, 3. -L)); 
run; 

/* prepare list of tables */ 
proc sql noprint; 
create table table_list as 
select distinct TABLE_NAME from WORK.SOURCE_PREP where not missing(table_name) 
; 
%let table_cnt=&sqlobs; 
select table_name into :table_list separated by ' ' from table_list; 
select table_name into :tab1 - :tab&table_cnt from table_list; 
quit; 

%put &table_list; 

%macro loop_when(cnt, var); 
    %do i=1 %to &cnt; 
     when ("&&&var.&i") output &&&var.&i; 
    %end; 
%mend; 

data &table_list; 
set WORK.SOURCE_PREP; 
    select (TABLE_NAME); 
     /* generate OUTPUT statements */ 
     %loop_when(&table_cnt, tab) 
    end; 
run; 
+0

很好的使用數據視圖。我改進了我自己的解決方案,只有一次讀取數據集(不包括初始PROC SQL步驟)。 – DavB 2013-02-20 08:25:33

+0

這很好,謝謝。 – immyh 2013-02-21 11:08:53

1

你可以試試這個:

%macro split(inds=,maxobs=); 

    proc sql noprint; 
    select distinct dept into :dept1-:dept9999 
    from &inds. 
    order by dept; 
    select ceil(count(*)/&maxobs.) into :numds1-:numds9999 
    from &inds. 
    group by dept 
    order by dept; 
    quit; 
    %let numdept=&sqlobs; 

    data %do i=1 %to &numdept.; 
     %do j=1 %to &&numds&i; 
      dept&&dept&i&&j. 
     %end; 
     %end;; 
    set &inds.; 
    by dept; 
    if first.dept then counter=0; 
    counter+1; 
    %do i=1 %to &numdept.; 
     %if &i.=1 %then %do; 
     if 
     %end; 
     %else %do; 
     else if 
     %end; 
       dept="&&dept&i" then do; 
     %do k=1 %to &&numds&i.; 
     %if &k.=1 %then %do; 
      if 
     %end; 
     %else %do; 
      else if 
     %end; 
       counter<=&maxobs.*&k. then output dept&&dept&i&&k.; 
     %end; 
     end; 
    %end; 
    run; 
%mend split; 

%split(inds=YOUR_DATASET,maxobs=3); 

%分配宏調用的INDS參數值只需更換您的輸入數據集的名稱。