簡體   English   中英

使用主鍵按列拆分SAS數據集

[英]Split SAS datasets by column with primary key

因此,我有一個具有一個主鍵的數據集: unique_id和1200個變量。 該數據集是從宏生成的,因此列數不會固定。 我需要將此數據集拆分為4個或更多的250個變量的數據集,這些較小的數據集均應包含主鍵,以便以后可以將其合並。 有人可以通過sas函數或宏來幫助我解決此問題嗎? 提前致謝。

按請求方式拆分數據集的一種簡單方法是對多個輸出數據集使用單個數據步驟,每個數據集都有一個KEEP =數據集選項,列出要保留的變量。 例如:

data split1(keep=Name Age Height) split2(keep=Name Sex Weight);
  set sashelp.class;
run;

因此,您需要獲取變量列表,然后將其分組為250個或更少的集合。 然后,您可以使用這些分組來生成上述代碼。 這是一種使用PROC CONTENTS獲取變量列表並使用CALL EXECUTE()生成代碼的方法。

我將使用宏變量保存輸入數據集的名稱,每個數據集需要保留的關鍵變量以及每個數據集中保留的最大變量數。

因此,對於上面的示例,這些宏變量值將是:

%let ds=sashelp.class;
%let key=name;
%let nvars=2;

因此,使用PROC CONTENTS來獲取變量名稱列表:

proc contents data=&ds noprint out=contents; run;

現在運行一個數據步驟,將它們拆分為組,並生成一個成員名稱以用於新的拆分數據集。 計數時,請確保不要在變量列表中包括KEY變量。

data groups;
  length group 8 memname $41 varnum 8 name $32 ;
  group +1;
  memname=cats('split',group);
  do varnum=1 to &nvars while (not eof);
    set contents(keep=name where=(upcase(name) ne %upcase("&key"))) end=eof;
    output;
  end;
run;

現在,您可以使用該數據集來驅動代碼的生成:

data _null_;
  set groups end=eof;
  by group;
  if _n_=1 then call execute('data ');
  if first.group then call execute(cats(memname,'(keep=&key'));
  call execute(' '||trim(name));
  if last.group then call execute(') ');
  if eof then call execute(';set &ds;run;');
run;

以下是SAS日志的結果:

NOTE: CALL EXECUTE generated line.
1    + data
2    + split1(keep=name
3    +  Age
4    +  Height
5    + )
6    + split2(keep=name
7    +  Sex
8    +  Weight
9    + )
10   + ;set sashelp.class;run;

NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: The data set WORK.SPLIT1 has 19 observations and 3 variables.
NOTE: The data set WORK.SPLIT2 has 19 observations and 3 variables.

使用宏變量的另一種方法是:

/* Number of columns you want in each chunk */

%let vars_per_part = 250;

/* Get all the column names into a dataset */

proc contents data = have out=cols noprint;
run;

%macro split(part);

  /* Split the columns into 250 chunks for each part and put it into a macro variable */

  %let fobs = %eval((&part - 1)* &vars_per_part + 1);
  %let obs  = %eval(&part * &vars_per_part);
  proc sql noprint;
    select name into :cols separated by " " from cols (firstobs =  &fobs obs = &obs) where name ~= "uniq_id";
    quit;

  /* Chunk up the data only keeping those varaibles and the uniq_id */
  data want_part∂
    set have (keep = &cols uniq_id);
  run;

%mend;

/* Run this from 1 to whatever the increment required to cover all the columnns */

%split(1);
%split(2);
%split(3);

這不是一個完整的解決方案,但是可以幫助您進一步了解如何解決此問題。 先前的解決方案在很大程度上依賴於proc的內容和數據步驟,但是我將使用proc sqldictionary.columns解決此問題。 然后,我將創建一個宏,該宏將根據需要將原始文件分成多個部分,每個部分250列。 步驟大致如下:

proc sql; create table as _colstemp as select * from dictionary.columns where library='your library' and memname = 'your table' and name ne 'your primary key'; quit;

計算以下位置所需的文件數:

proc sql; 
    select ceil(count(*)/249) into :num_of_datasets from _colstemp; 
    select count(*) into :num_of_cols from _colstemp; 
quit;

然后只需遍歷原始數據集即可:

%do &_i = 1 %to &num_of_datasets

proc sql; 
    select name into :vars separated by ',' 
    from _colstemp(firstobs=%eval((&_i. - 1)*249 + 1) obs = %eval(min(249,&num_of_cols. - &_i. * 249)) ;
quit;

proc sql; 
    create table split_&_i. as
    select YOUR_PRIMARY_KEY, &vars from YOUR_ORIGINAL_TABLE;
quit;
%end;

希望這給您另一個想法。 該解決方案未經測試,可能包含一些偽代碼元素,因為它是從我做事的記憶中編寫的。 同樣,這也沒有宏聲明,也可以做很多參數化操作。這將使解決方案更加通用(例如,對每個數據集的變量數量,主鍵名稱和數據集名稱進行參數化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM