データの操作#

これまでにSASにデータを読み込み、DATAステップでSAS変数を操作する方法を扱ったので、次にはデータセットの基本的な操作についてを扱います。このセクションでは、以下の操作を行う方法を見ていきます。

  1. SASデータセットの行をWHERE、IF、OBS、FIRSTOBSを使用してサブセットする

  2. SAS変数リストを使用してSASデータセットの列をDROPまたはKEEPを使用してサブセットする

  3. SASデータセットに列/新しい変数を追加する

  4. 変数の属性を変更するために、変数名を変更し、SAS変数にラベルを追加し、変数の長さを変更する

  5. PROC SORTを使用してSASデータセットの行を並べ替える

SASデータセットをサブセットする方法#

既存のSASデータセットから作成されたサブセットを使用すると、元の大きなデータセットと比較してコンピュータリソースをより効率的に利用することができます。オブザベーションを読み込む回数が少ないため、DATAステップの反復回数が減少します。

SASで行をサブセットする方法はいくつかあります。

  • FIRSTOBS=およびOBS=のデータセットオプション

  • サブセットIFまたはWHEREステートメント

FIRSTOBS=およびOBS=オプション#

まず、FIRSTOBSおよびOBSのデータセットオプションを使用してみましょう。

  • データセットオプションの**FIRSTOBS=**オプションは、データセットからデータを読み込む開始行番号を指示します

  • データセットオプションの**OBS=**オプションは、データセットからデータを読み込むのを終了する行番号を指示します

このセクションを通じて使用するデータセットを作成するために、まずOBS=オプションを使用します。使用するデータセットは、国立健康研究所の間質性膀胱炎データベース(ICDB)研究に登録された638人の人口統計(または「背景」)情報を収集したものです。ICDB研究は、間質性膀胱炎という病気についての理解が不足しているため、その研究が行われた主な理由です。間質性膀胱炎は、特定の原因がないにもかかわらず、重篤な膀胱と骨盤痛、頻尿、排尿痛を引き起こす病気です。女性に比べて男性にも影響を及ぼし、すべての年齢層にわたります。(ICDB研究についてもっと学びたい場合は、国立健康研究所のウェブサイトを参照してください。そこでは試験の概要が提供されています)

ICDB研究の背景データを使用するにあたって、データが収集された背景の調査票を確認しておくことが役立つでしょう。このセクションのSASプログラムを実行するには、back.sas7bdatという背景データセットをコンピュータのフォルダにダウンロードして保存する必要があります(READMEを参照)。

#

以下のプログラムのデータステップでは OBS= オプションを使い、永久データセットicdb.back の先頭25行により一時データセット back を作成しています。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';
 
data back;
  set PHC6089.back (obs=25);
run;

title 'A Subset of the Background Data Set'; 
proc print data=back (obs = 10);
run;
SAS 出力

A Subset of the Background Data Set

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 110027 0 10/05/93 2068 07/05/62 2 5 1 4 0 0 1 3 1 . 2
2 110029 0 10/05/93 2068 09/07/26 2 5 1 4 0 2 1 5 8 . 2
3 110039 0 12/07/93 2068 07/24/24 2 22 1 4 0 3 1 3 8 . 2
4 110040 0 11/30/93 2068 10/20/67 2 32 1 4 0 7 1 5 1 . 2
5 110045 0 01/11/94 2068 04/18/25 1 36 1 4 0 3 1 1 8 0 2
6 110049 0 01/25/94 2068 10/05/23 2 37 1 4 0 1 1 5 8 0 2
7 110051 0 01/25/94 2068 12/02/42 2 42 1 4 0 3 1 3 1 0 2
8 110052 0 01/27/94 1808 01/04/25 2 5 1 4 0 0 1 4 8 0 2
9 110053 0 02/22/94 1808 03/15/22 2 5 1 4 1 3 1 1 8 0 1
10 110055 0 03/15/94 1808 03/31/41 2 5 1 4 0 0 1 3 1 0 2

プログラムは非常にシンプルです。主なポイントは、OBS=オプションを( )で囲む必要があるということです。
まだデータを入手していない場合は、背景データセット(README参照)をコンピュータ上の任意の場所にダウンロードして保存します。その後プログラムを開き、LIBNAMEステートメントを編集して、データセットを保存した場所を反映させます。その後、プログラムを実行し、PRINTプロシージャからの出力を確認して、データセットについて理解を深めましょう。

#

以下のプログラムでは、データセットオプションのFIRSTOBS=とOBS=オプションを使用して、永久データセットicdb.back の14オブザベーション(オブザベーション7、8、9、…、20)を一時データセットbackに含めるように指示しています。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back1;
  set phc6089.back (firstobs=7 obs=20);
run;

title 'Output Dataset: BACK1'; 
proc print data=back1; 
run;
SAS 出力

Output Dataset: BACK1

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 110051 0 01/25/94 2068 12/02/42 2 42 1 4 0 3 1 3 1 0 2
2 110052 0 01/27/94 1808 01/04/25 2 5 1 4 0 0 1 4 8 0 2
3 110053 0 02/22/94 1808 03/15/22 2 5 1 4 1 3 1 1 8 0 1
4 110055 0 03/15/94 1808 03/31/41 2 5 1 4 0 0 1 3 1 0 2
5 110057 0 03/15/94 2068 07/10/44 2 5 1 4 0 3 1 4 2 0 2
6 110058 0 03/18/94 1808 09/09/50 2 . 13 4 1 0 1 3 1 0 1
7 110059 0 03/18/94 1808 07/25/34 2 13 1 4 0 1 1 3 8 0 1
8 110060 0 06/14/94 1808 05/29/36 2 13 1 4 0 3 1 3 1 0 2
9 110062 0 03/31/94 1808 04/21/36 2 3 1 4 0 1 1 4 5 0 2
10 110065 0 04/04/94 1808 10/12/52 2 5 1 4 0 3 1 4 4 1 1
11 110066 0 04/12/94 1808 08/28/62 2 5 1 4 0 0 1 4 6 0 2
12 110067 0 04/26/94 1808 02/22/72 2 5 1 4 0 1 6 4 2 0 2
13 110068 0 06/13/94 1808 09/10/55 2 25 1 4 0 11 1 3 7 0 2
14 110069 0 05/31/94 1808 08/17/38 2 32 1 4 0 0 1 3 1 0 2

プログラムを開いてLIBNAMEステートメントを編集して、背景データセットを保存した場所を反映させます。その後、プログラムを実行し、PRINTプロシージャからの出力を確認します。前の例からの出力と比較して、一時的なデータセットback1が実際に14オブザベーション(元の背景データセットのオブザベーション7、8、…、20)を含んでいることを、出力を比較して確認してみてください。

WHERE=データセットオプションン、WHEREステートメント、およびサブセット化IF#

WHERE=データセットオプションを使うと、特定の条件を満たすデータセットからのみオブザベーションを選択できます。WHERE=データセットオプションをSETステートメントまたはDATAステートメントに付加できます。WHERE=データセットオプションをSETステートメントに付加すると、SASはデータを読み込む際に条件を満たすオブザベーションを選択します。WHERE=データセットオプションをDATAステートメントに付加すると、SASはプログラムデータベクトル(PDV)からデータをアウトプットデータセットに書き込む際にオブザベーションを選択します。

#

以下のプログラムでは特定の条件を満たすオブザベーションをwhere=データセットオプションにより抽出しています。where=データセットオプションはDTATステートメントに設定されているため、PDVからデータセットに出力する際に抽出が行われます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data temple (where = (int(subj/10000)=23)) 
     okla (where = (int(subj/10000)=31));
  set phc6089.back;
run;

title 'Output Dataset: TEMPLE'; 
proc print data=temple;
run;

title 'Output Dataset: OKLA'; 
proc print data=okla (obs = 10); 
run;
SAS 出力

Output Dataset: TEMPLE

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 230003 0 07/09/93 5396 10/25/47 2 22 1 4 0 1 4 3 1 . 1
2 230004 0 01/04/94 5396 08/15/23 2 38 1 4 0 1 5 3 5 0 1
3 230005 0 01/06/94 5396 05/25/49 2 10 1 3 0 3 2 4 1 0 2
4 230006 0 01/06/94 5396 04/24/49 2 21 1 4 0 3 1 5 5 1 2
5 230008 0 10/03/96 5396 08/09/60 2 38 1 4 0 1 1 4 2 0 2
6 230009 0 10/31/96 5396 11/13/50 1 38 1 4 0 1 1 3 1 0 2

Output Dataset: OKLA

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 310020 0 06/18/93 1916 08/09/43 2 43 1 4 0 3 1 5 1 . 2
2 310032 0 08/03/93 1916 04/02/34 2 13 1 4 0 1 1 1 8 . 1
3 310037 0 11/08/93 1916 04/25/39 2 36 1 4 0 1 1 3 7 . 2
4 310041 0 10/27/93 1916 11/01/26 2 43 1 4 0 3 1 4 5 . 2
5 310049 0 02/04/94 1916 10/03/31 2 25 1 4 0 3 1 4 8 1 2
6 310055 0 07/12/94 1916 12/11/56 2 36 1 4 0 3 1 4 1 1 1
7 310056 0 04/01/94 1916 11/16/61 2 36 1 4 0 3 1 4 1 0 2
8 310059 0 06/13/94 1916 08/22/34 2 43 1 4 0 1 1 4 8 0 2
9 310065 0 06/30/94 1916 07/27/56 2 36 1 4 0 0 1 4 1 0 2
10 310069 0 09/23/94 1916 07/14/42 2 36 1 4 0 3 3 3 7 1 1

さて、これは実際にはそんなに単純ではありません。このプログラムは、特定の変数の値に基づいて大きなデータセットを小さなデータセットに分割するために、where=データセットオプションの使用する方法を示しています。DATAステートメントで見ると、実際には2つのデータセット名「temple」と「okla」が指定されています。これはSASに、この1つのDATAステップ内で2つのデータセットを作成したいことを伝えています。templeはTemple Universityに登録された被験者のみ、もう一方のoklaは、University of Oklahomaに登録された被験者のみが含まれるようになっています。この処理には、ICDB研究で使用される被験者番号について、およびINT関数の機能について理解しておく必要があります:

  • 変数「subj」には6桁の被験者番号が含まれています。被験者番号の最初の2桁は、被験者が登録された場所を示します。被験者番号の最初の2桁が23であれば、被験者はTemple Universityに登録されました。被験者ID番号の最初の2桁が31であれば、被験者はUniversity of Oklahomaに登録されました。

  • 思い出したかもしれませんが、INT関数は( )内の式の整数部分を返します。したがって、被験者番号が230007であれば、int(subj/10000) = int(23.0007) = 23でTemple UniversityのIDになります。

where=データセットオプションの構文に注意が必要……気をつけなければ、混乱する可能性があります。where=データセットオプション全体は、適用したいデータセットの直後に( )で囲まれた状態で続けなければなりません。条件自体も( )で囲まれています。一般的には、DATAステートメントに適用される場合の構文は次のようになります:

DATA dsname (WHERE = (condition));

ここで、dsnameはデータセット名で、conditionはオブザベーションを選択するのにSASが評価する条件です。

プログラムを実行する前に、LIBNAMEステートメントのディレクトリを編集して、背景データセットを保存した場所を反映させます。LIBNAMEステートメントを編集した後、SASプログラムを実行します。ICDB背景データセットのオブザベーションがTemple Universityに登録された被験者に対応するものが、一時データセットtempleに含まれていること、そしてUniversity of Oklahomaに登録された被験者に対応するオブザベーションが、一時データセットoklaに含まれていることを出力から確認してみてください。

追加のコメント where=データセットオプションを使用すると、条件はその直前のデータセットにのみ適用されます。代わりに入力データセット全体に条件を適用するWHEREステートメントを使用することもできます。また、where=データセットオプションはFIRSTOBS=またはOBS=オプションと同時に使用できないことに注意してください。

#

以下のプログラムはデータセットオプションのWHERE=オプションの効率的な利用法です。WHERE=オプションはSETステートメントで指定されているため、抽出プロセスはicdb.backを読み込む際に行われます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data temple2;
  set phc6089.back (where = (int(subj/10000)=23));
run;

title 'Output Dataset: TEMPLE2'; 
proc print data = temple2;  
run;
SAS 出力

Output Dataset: TEMPLE2

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 230003 0 07/09/93 5396 10/25/47 2 22 1 4 0 1 4 3 1 . 1
2 230004 0 01/04/94 5396 08/15/23 2 38 1 4 0 1 5 3 5 0 1
3 230005 0 01/06/94 5396 05/25/49 2 10 1 3 0 3 2 4 1 0 2
4 230006 0 01/06/94 5396 04/24/49 2 21 1 4 0 3 1 5 5 1 2
5 230008 0 10/03/96 5396 08/09/60 2 38 1 4 0 1 1 4 2 0 2
6 230009 0 10/31/96 5396 11/13/50 1 38 1 4 0 1 1 3 1 0 2

プログラムを実行する前に、LIBNAMEステートメントのディレクトリを、背景データセットを保存した場所を反映するように変更してください。LIBNAMEステートメントを編集したら、プログラムを実行します。PRINTプロシージャからの出力を確認してください。temple2データセットには、ICDB背景データセットからのemple Universityに登録された被験者のオブザベーションが含まれていることを確認してください。

他には、特定のオブザベーションをすべての出力データセットから除外したい場合、以下の方法があります。

  • 特定の条件を満たす行を含めるためにWHEREステートメントまたはサブセット化IFを使用する

  • 特定の条件を満たす行を除外するためにIf-Then-Deleteを使用する

#

次のプログラムは、被験者IDが23で始まるレコードのみを保持するためにWHEREステートメントを使用する例を示しています。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data temple3;
  set phc6089.back;
  where (int(subj/10000)=23);
run;

title 'Output Dataset: TEMPLE3'; 
proc print data = temple3;
run;
SAS 出力

Output Dataset: TEMPLE3

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 230003 0 07/09/93 5396 10/25/47 2 22 1 4 0 1 4 3 1 . 1
2 230004 0 01/04/94 5396 08/15/23 2 38 1 4 0 1 5 3 5 0 1
3 230005 0 01/06/94 5396 05/25/49 2 10 1 3 0 3 2 4 1 0 2
4 230006 0 01/06/94 5396 04/24/49 2 21 1 4 0 3 1 5 5 1 2
5 230008 0 10/03/96 5396 08/09/60 2 38 1 4 0 1 1 4 2 0 2
6 230009 0 10/31/96 5396 11/13/50 1 38 1 4 0 1 1 3 1 0 2

WHEREステートメントには「=」がないことに注意してください。これは、WHERE=データセットオプションを使用するのとは対照的です。代わりに、サブセット化Ifを使うこともできます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data temple4;
  set phc6089.back;
  if (int(subj/10000)=23);
run;

title 'Output Dataset: TEMPLE4'; 
proc print data = temple4;  
run;
SAS 出力

Output Dataset: TEMPLE4

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 230003 0 07/09/93 5396 10/25/47 2 22 1 4 0 1 4 3 1 . 1
2 230004 0 01/04/94 5396 08/15/23 2 38 1 4 0 1 5 3 5 0 1
3 230005 0 01/06/94 5396 05/25/49 2 10 1 3 0 3 2 4 1 0 2
4 230006 0 01/06/94 5396 04/24/49 2 21 1 4 0 3 1 5 5 1 2
5 230008 0 10/03/96 5396 08/09/60 2 38 1 4 0 1 1 4 2 0 2
6 230009 0 10/31/96 5396 11/13/50 1 38 1 4 0 1 1 3 1 0 2

代わりに、被験者IDが23で始まらないオブザベーションを除外したい場合は、If-Then-Deleteステートメントを使用する必要があります。次のプログラムは、被験者IDが23で始まらない行を削除します。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data temple5;
  set phc6089.back;
  if (int(subj/10000) ne 23) Then DELETE;
run;

title 'Output Dataset: TEMPLE5'; 
proc print data = temple5;
run;
SAS 出力

Output Dataset: TEMPLE5

OBS subj v_type v_date r_id b_date sex state country race ethnic relig mar_st ed_level emp_st job_chng income
1 230003 0 07/09/93 5396 10/25/47 2 22 1 4 0 1 4 3 1 . 1
2 230004 0 01/04/94 5396 08/15/23 2 38 1 4 0 1 5 3 5 0 1
3 230005 0 01/06/94 5396 05/25/49 2 10 1 3 0 3 2 4 1 0 2
4 230006 0 01/06/94 5396 04/24/49 2 21 1 4 0 3 1 5 5 1 2
5 230008 0 10/03/96 5396 08/09/60 2 38 1 4 0 1 1 4 2 0 2
6 230009 0 10/31/96 5396 11/13/50 1 38 1 4 0 1 1 3 1 0 2

SASデータセットの列のサブセット化#

変数の数を減らしてデータセットのサイズを小さくしたい場合があるかもしれません。このようなことを「データセットを細くする」と表現することもあります。データセットから特定の変数を選択するには、以下のいずれかの方法があります。

  • DROPステートメントまたはDROP=データセットオプションを使って、除外する変数を選択する

  • KEEPステートメントまたはKEEP=データセットオプションを使って、含める変数を選択する

この利点は、少ない変数を読み込むことができれば、SASはより小さなプログラムデータベクトルを使用し、より効率的に実行されることです。

どちションまたはステートメントを使うべきでしょうか? DROPとKEEPのどちらを使うかは個人的な選択ですが、多くの人は必要なタイピングが少ない方を選ぶでしょう。しかし私の場合は可能な限りKEEPを使います。そうすればプログラムを読めばデータセットにどの変数が含まれているかを知ることができるからです。一方、DROPを使う場合データセットにどの変数が含まれていたかを考える必要があります。

#

次のプログラムは、データセットback1から読み込む際に、「subj」、「v_date」、「b_date」の3つの変数のみを保持するようにして、データセットback2を作成します。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back2;
  set phc6089.back (keep = subj v_date b_date);
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK2'; 
proc print data=back2 (obs=5);
run;
SAS 出力

Output Dataset: BACK2

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

データセットオプションのKEEP=オプションは、データセットbackから被験者ID「subj」、来院日「v_date」、生年月日「b_date」の3つの変数を読み込み、新しい一時データセットback2に格納するようSASに指示するものです。KEEP=オプションは、変数を選択したいデータセットの名前の後ろに続けて、( )の中に置く必要があることに注意してください。指定する保持する変数のリストは、少なくとも1つのスペースで区切る必要があります。
次に、来院時の被験者の年齢(age)は、来院日(v_date)から生年月日(b_date)を引いて365で割ることで(概算の)年齢として計算されます。
SASプログラムを開いて実行し、PRINTプロシージャからの出力を確認して、一時データセットback2に保持された3つの変数(subj、v_date、b_date)と、新しく計算された変数「age」が含まれていることを確認してください。
代わりに、keepステートメントを使うこともできます。上の例でデータセットオプションのkeep=を使うメリットは、必要な変数だけを読み込んだことです。次のコードでは、すべての変数をDATAステップに読み込み、選択した変数のみをデータセットback3に出力します。
新しい変数「age」もkeepステートメントに入れる必要があることに注意してください。前のデータセットオプションのkeep=オプションは、SETステートメントの入力データセットにのみ適用されていましたが、keepステートメントはデータステップ内のすべての変数に適用されます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back3;
  set phc6089.back; 
  keep subj v_date b_date age;
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK3'; 
proc print data=back3 (obs=5);    
run;
SAS 出力

Output Dataset: BACK3

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

keep=オプションをDATAステートメントのオプションとしても使うことができます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back3a (keep= subj v_date b_date age);
  set phc6089.back; 
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK3a'; 
proc print data=back3a (obs=5);    
run;
SAS 出力

Output Dataset: BACK3a

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

同じ結果を得る別の方法に、DROPを使って必要のない変数を除外する方法があります。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back4;
  set phc6089.back (drop = v_type r_id sex state country 
                           race ethnic relig mar_st
                           ed_level emp_st job_chng income);
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK4'; 
proc print data=back4 (obs = 5);    
run;
SAS 出力

Output Dataset: BACK4

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

SETステートメントのDROP=オプションは、13の変数(来院タイプ「v_type」、データフォームの確認者のID「r_id」、被験者の性別「sex」、居住州「state」、居住国「country」、人種「race」、民族「ethnic」、宗教「relig」、婚姻状況「mar_st」、教育レベル「ed_level」、雇用状況「emp_st」、職業変更状況「job_chng」、収入「income」)をデータセットbackから除外し、残りの変数を新しい一時データセットback3に格納するようSASに指示します。したがって、データセットback3を作成するためのプログラムデータベクトルには、被験者ID「subj」、来院日「v_date」、生年月日「b_date」の3つの変数のみが含まれます。
KEEP=オプションと同様に、DROP=オプションは( )の中に置き、除外したい変数があるデータセットの名前の後ろに続ける必要があることに注意してください。指定する除外する変数のリストは、少なくとも1つのブランクスペースで区切る必要があります。
DROPステートメントを使うこともできます。ただし、この場合SASはすべての変数をSASデータベクトルに読み込み、出力するデータセットでドロップしない変数のみを出力します。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back5;
  set phc6089.back;
  drop v_type r_id sex state country 
       race ethnic relig mar_st
       ed_level emp_st job_chng income;
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK5'; 
proc print data=back5 (obs = 5);    
run;
SAS 出力

Output Dataset: BACK5

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

あるいは、データセットオプションのdrop=オプションを使うこともできます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back5a (drop = v_type r_id sex state country 
       race ethnic relig mar_st
       ed_level emp_st job_chng income);
  set phc6089.back;
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK5a'; 
proc print data=back5a (obs = 5); 
run;
SAS 出力

Output Dataset: BACK5a

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

すべての変数をリストアップするのは非常に面倒な作業になります。そこでSASは変数リストを作成するためのショートカットを提供しています。var1 – var2 の形式のリストを指定できます。「var1」と「var2」はSASデータセット内の2つの変数名です。--はSASに「これら2つの列の間にあるすべての変数を埋める」ように指示します。

PROC CONTENTSにVARNUMオプションを使ってデータセット内の列の順序を見ると、「sex」から「income」までの列が連続して並んでいることがわかります。これにより、DROPステートメントを次のように短縮することができます。

DROP v_type r_id sex -- income;
ods select Position;
proc contents data = phc6089.back order=varnum;
run;
ods select all;
SAS 出力

Output Dataset: BACK5a

CONTENTS プロシジャ

作成順の変数
# 変数 タイプ 長さ 出力形式
1 subj 数値 8  
2 v_type 数値 8  
3 v_date 数値 8 MMDDYY8.
4 r_id 数値 8  
5 b_date 数値 8 MMDDYY8.
6 sex 数値 8  
7 state 数値 8  
8 country 数値 8  
9 race 数値 8  
10 ethnic 数値 8  
11 relig 数値 8  
12 mar_st 数値 8  
13 ed_level 数値 8  
14 emp_st 数値 8  
15 job_chng 数値 8  
16 income 数値 8  
libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back6;
  set phc6089.back;
  drop v_type r_id sex -- income;
  age = (v_date - b_date)/365;  * Calculate AGE in years;
  format age 4.1;
run;

title 'Output Dataset: BACK6'; 
proc print data=back6 (obs = 5);
run;
SAS 出力

Output Dataset: BACK6

OBS subj v_date b_date age
1 110027 10/05/93 07/05/62 31.3
2 110029 10/05/93 09/07/26 67.1
3 110039 12/07/93 07/24/24 69.4
4 110040 11/30/93 10/20/67 26.1
5 110045 01/11/94 04/18/25 68.8

何を使うべきか#

前の4つの例を見直すと、頭がクラクラしてくるかもしれません。SETステートメントでデータセットオプションのKEEP=オプション、DROP=オプション、DATAステートメントでデータセットオプションのKEEP=オプション、DROP=オプションのどれを使えばよいのか分からなくなったかもしれません。どれを使うべきかを判断するのに役立つ主な項目は次のとおりです。

  • 前述したように、KEEPとDROPを選ぶのは個人の選択次第です。データセットオプションをSETステートメント、DATAステートメントのどちらに置くか、または個別のステートメントを使うかが違いになります。

  • SETステートメントでは、DROP=とKEEP=オプションは入力SASデータセットからどの変数を読み込むかを決定します。つまり、SETステートメントでDROP=またはKEEP=オプションを指定すると、除外された変数はプログラムデータベクトルに読み込まれません。

  • DATAステートメントでは、DROP=とKEEP=オプションはプログラムデータベクトルからどの変数を出力SASデータセットに書き込むかを決定します。つまり、DATAステートメントでDROP=またはKEEP=オプションを指定すると、入力データセットのすべての変数がプログラムデータベクトルに読み込まれますが、選択された変数のみがプログラムデータベクトルから出力データセットに書き込まれます。これにより、単一のDATAステップで出力データセットごとに異なる変数セットをキープ/ドロップして、複数のデータセットを作成することができます。

  • 個別のDROPおよびKEEPステートメントは、DATAステートメントのデータセットオプションと同様に機能しますが、DATAステートメントにリストされたすべてのデータセットに適用されます。

これらのことを踏まえると、不要な変数を入力データセットから読み込まない、より効率的なDATAステップを構築できることが明らかになります。したがって、次のような作業方針を立てることができます。

  • SET ステートメントでデータセットオプションの KEEP= オプション (または DROP= オプション) を使って、プログラムの目的を達成するために必要な変数のみを入力データセットからプログラムデータベクトルに読み込むよう SAS に指示する

  • data ステートメントでデータセットオプションのKEEP= オプション (または DROP= オプション) 、または個別のステートメントを使って、プログラムデータベクトルから出力データセットに書き込みたいすべての変数を指定する。data ステートメントで複数のデータセットに異なる変数を選択したい場合は、data ステートメントでデータセットオプションを使う必要があります。

この方針を例で試してみましょう。

#

次のプログラムは、SETステートメントでデータセットオプションのKEEP=オプションを使うタイミングと、DATAステートメントでデータセットオプションのKEEP=オプションを使うタイミングについての方針を示しています。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back6 (keep = subj age);
  set phc6089.back (keep= subj v_date b_date);
  age = (v_date - b_date)/365;
  format age 4.1;
run;

title 'Output Dataset: BACK6'; 
proc print data=back6 (obs=5);  
run;
SAS 出力

Output Dataset: BACK6

OBS subj age
1 110027 31.3
2 110029 67.1
3 110039 69.4
4 110040 26.1
5 110045 68.8

ここでは、SETステートメントでのデータセットオプションのKEEP=オプションは、入力データセットから「subj」、「v_date」、「b_date」の3つの変数のみを保持するようにしています。「v_date」と「b_date」は、「age」を計算するために必要なので保持されています。被験者の年齢は、「v_date」から「b_date」を引いて365で割ることで計算されます。したがって、プログラムデータベクトルには 「subj」、「v_date」、「b_date」、「age」の4つの変数が含まれ、それらのうちいくつでも出力データセット back6 に書き込むことができます。DATAステートメントのデータセットオプションのKEEP=オプションは、プログラムデータベクトルからどの変数を出力データセットに書き込むかを指定します。ここでは、被験者ID(subj)と年齢(age)のみをback6に書き込むようにしています。

プログラムを開いて実行し、PRINTプロシージャの出力から一時データセットback6に実際に被験者ID(subj)と年齢(age)のみが含まれていることを確認してください。

変数属性の変更: RENAME=およびLABELオプション#

データセットのディスクリプタ部には、データセット内の各変数の属性情報が含まれています。属性情報には、変数名、型、長さ、フォーマット、インフォーマット、ラベルが含まれます。ここでは、以下の方法を扱います。

  • LENGTHステートメントを使って変数の既定の長さを調整する

  • RENAME=オプションを使って変数名を変更する

  • LABELステートメントを使って変数に説明ラベルを付加する

フォーマットについては後のセクションで扱います。

RENAME=オプション#

SASデータセット内の変数名を変更したい場合があるかもしれません。その場合はデータセットオプションのRENAME=オプションを使います。RENAME=オプションを使えば、SASデータセット内の変数名を変更できます。

RENAME=オプションの形式は次のとおりです。

RENAME = (old1=new1 old2=new2 .... oldk=newk);

ここで、「old1」、「old2」、…、「oldk」はRENAME=オプションの前のデータセットに含まれる変数名で、「new1」、「new2」、…、「newk」はそれぞれの新しい変数名です。

データセットオプションのRENAME=オプションの効果は、オプションの位置によって異なります。

  • RENAME=オプションがSETステートメントのデータセットオプションにある場合、新しい変数名はプログラムデータベクトルが作成された時点で有効になります。したがって、DATAステップ内のすべてのプログラムで、新しい変数名を参照する必要があります

  • RENAME=オプションがDATAステートメントのデータセットオプションにある場合、新しい変数名はデータをSASデータセットに書き込む時点で有効になります。したがって、DATAステップ内のすべてのプログラムでは、古い変数名を参照する必要があります

#

以下のプログラムは、SETステートメントにおけるRENAME=オプションの使用例を示しています。具体的には、変数「sex」が「gender」に、「b_date」が「birth」に変更されています。これにより、プログラムデータベクトルが作成されます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back7 (keep = subj gender v_date birth age);
  set phc6089.back (rename=(sex=gender b_date=birth));
  age = (v_date - birth)/365;   *MUST use NEW name for date of birth;
run;

title 'Output Dataset: BACK7'; 
proc print data=back7 (obs=5);    
run;
SAS 出力

Output Dataset: BACK7

OBS subj v_date birth gender age
1 110027 10/05/93 07/05/62 2 31.2740
2 110029 10/05/93 09/07/26 2 67.1233
3 110039 12/07/93 07/24/24 2 69.4192
4 110040 11/30/93 10/20/67 2 26.1315
5 110045 01/11/94 04/18/25 1 68.7808

RENAME=オプションがSETステートメントのデータセットオプションで使われているため、「sex」を性別、「b_date」を生年月日と認識しなくなります。代わりに、「gender」と「birth」を認識するようになります。したがって、その後にDATAステップで被験者の年齢(age)を計算する際には、新しい変数名「birth」を参照する必要があります。
RENAME=オプションの構文にも注意が必要です。RENAME=オプション全体は、名前を変更したいデータセットの後ろに続けて()で囲む必要があります。変数名も()で囲む必要があります。したがって、一般的にDATAステートメントに適用する場合の構文は以下のようになります。

data dsname (RENAME = (o1=n1 o2=n2 ...));

ここで「dsname」はデータセット名、「o1」と「o2」は古い変数名、「n1」と「n2」は新しい変数名です。
プログラムを開いて実行し、PRINTプロシージャの出力を確認してください。「sex」と「b_date」がそれぞれ「gender」と「birth」に変更されたことを確認してください。また、被験者の年齢が適切に計算されていることも確認してください。次に、プログラムで変数名「birth」を元の「b_date」に戻し、プログラムを再実行してください。SASがエラーを出すはずです。

#

次の例は、RENAME=オプションがDATAステートメントで使われる例を示しています。具体的には、変数「sex」が「gender」に、「b_date」が「birth」に、データセットに書き込みまれる際に変更されます。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back8 (rename=(sex=gender b_date=birth)
            keep = subj sex v_date b_date age);
  set phc6089.back;
  age = (v_date - b_date)/365; *MUST use OLD name 
                                for date of birth;
run;

title 'Output Dataset: BACK8'; 
proc print data=back8 (obs=5);    
run;
SAS 出力

Output Dataset: BACK8

OBS subj v_date birth gender age
1 110027 10/05/93 07/05/62 2 31.2740
2 110029 10/05/93 09/07/26 2 67.1233
3 110039 12/07/93 07/24/24 2 69.4192
4 110040 11/30/93 10/20/67 2 26.1315
5 110045 01/11/94 04/18/25 1 68.7808

RENAME=オプションがDATAステートメントのデータセットオプションで使われているため、SASは変数名をデータセットback3の名前として認識します。つまり、SASは「b_date」という変数名を被験者の生年月日として認識します。したがって、その後にDATAステップで被験者の年齢を計算する際には、古い変数名「b_date」を参照する必要があります。また、DATAステートメントのKEEP=オプションは、データセットback3の元の変数名を参照しなければならないことにも注意してください。
このプログラムは、複数のDATAステップオプションを同時に使用する方法も示しています。具体的にはRENAME=とKEEP=オプションを使ってデータセットback8を変更しています。このように、変更を加えたいデータセットの後ろに、それらのオプションを()の中に入れます。そして、その()内ではそれぞれのオプションの基本的な構文に従います。
プログラムを開いて実行し、PRINTプロシージャの出力を確認してください。変数名「sex」と「b_date」がそれぞれ「gender」と「birth」に変更されたことを確認してください。また、被験者の年齢が適切に計算されていることも確認してください。

LABELステートメント#

LABELステートメントは、変数に説明的なラベルを設定します。このラベルは、変数名の代わりに出力時に使用されます。グラフを作成する際には、ラベルが軸のラベルとして使用されます。

#

以下のプログラムでは、LABELステートメントを使って変数「subj」、「sex」、「v_date」、「b_date」、「age」に説明的なラベルを設定しています。

libname PHC6089 '/folders/myfolders/SAS_Notes/data/';

data back8a (rename=(sex=gender b_date=birth)
            keep = subj sex v_date b_date age);
  set phc6089.back;
  age = (v_date - b_date)/365; *MUST use OLD name 
                                for date of birth;
  label subj = "Subject ID"
        sex = "Gender"
        v_date = "Visit Date"
        b_date = "Birth Date"
        age = "Age in Years";
run;

title ;
ODS SELECT Position;
proc contents data = back8a order = varnum;
run;
ODS SELECT ALL;
SAS 出力

CONTENTS プロシジャ

作成順の変数
# 変数 タイプ 長さ 出力形式 ラベル
1 subj 数値 8   Subject ID
2 v_date 数値 8 MMDDYY8. Visit Date
3 birth 数値 8 MMDDYY8. Birth Date
4 gender 数値 8   Gender
5 age 数値 8   Age in Years

ラベルが追加されたことは、PROC CONTENTSでデータセットのディスクリプタ部を表示すれば確認できます。ラベルは最大256文字まで指定できます。

LENGTHステートメント#

前で触れたように、デフォルトでは文字型変数の長さは8文字です。これまでは、8文字より長い文字列を読み込む際には、文字インフォーマットやカラム入力を使っていました。別の方法として、LENGTHステートメントを使って変数長の属性を8文字より長く設定することができます。

#

以下のプログラムは、デフォルトの長さと、LENGTHステートメントを使って長さを長くした場合の文字値の作成例です。

data char_length;
  length char_var2 $20;
  infile datalines delimiter = ",";
  input char_var1 $ char_var2 $;
  datalines;
A longer character string, A longer character string
shortChar, shortChar
;
run;

title "Character Length Data Example";
proc print data = char_length;   
run;
SAS 出力

Character Length Data Example

OBS char_var2 char_var1
1 A longer character s A longer
2 shortChar shortCha

LENGTHステートメントは、「char_var2」の長さを最大20文字に設定していますが、「char_var1」はデフォルトの8文字のままです。同じ文字値を読み込む際、「char_var1」は最初の8文字までしか格納できず、残りを破棄してしまいますが、「char_var2」は20文字まで格納できます。このため、「char_var1」では文字列が部分的にしか読み込まれません。

データセットの行の並べ替え: PROC SORT#

デフォルトでは、PRINTプロシージャはデータセットのオブザベーションをデータセット内の出現順に表示します。SORTプロシージャを使うことで、1つ以上の変数の値に基づいてデータセットを事前に並べ替えることができます。その後、PRINTプロシージャを使うと、SASはオブザベーションを並べ替えた順序で表示します。

#

以下のプログラムでは、SORTプロシージャを使って、前に作成した一時データセットback8を「gender」でまず並べ替え、次に「age」で並べ替えています。「gender」で最初に並べ替えられ、「gender」が同じ場合は「age」でさらに並べ替えられることに注意してください。

proc sort data = back8 out = srtd_back8;
  by gender age;
run;

title "First 5 sorted observations for gender  = 1";
proc print data = srtd_back8 (obs = 5);
  var gender age subj v_date birth;
run;

title "First 5 sorted observations for gender  = 2";
proc print data = srtd_back8 (firstobs = 57 obs = 62);
  var gender age subj v_date birth;
run;
SAS 出力

First 5 sorted observations for gender = 1

OBS gender age subj v_date birth
1 1 -18.3014 110125 02/06/96 05/22/14
2 1 -17.3699 110152 07/19/96 11/27/13
3 1 23.4986 410073 06/13/95 12/19/71
4 1 23.6822 520051 09/26/94 01/26/71
5 1 24.8630 410071 05/30/95 07/25/70

First 5 sorted observations for gender = 2

OBS gender age subj v_date birth
57 2 -23.1534 410097 04/24/96 06/14/19
58 2 -22.6795 420074 09/07/95 05/07/18
59 2 -22.6466 520007 08/13/93 03/31/16
60 2 -22.2438 310102 02/12/96 05/06/18
61 2 -22.1781 420112 12/17/96 02/15/19
62 2 -20.3041 510010 09/21/93 01/05/14

プログラムを開き、FIRSTOBSおよびOBSデータセットオプションを削除して、データセットが性別と年齢でソートされていることを確認して、全体のデータセットを出力します。
BYステートメントは必須ですが、SORTプロシージャのOUT=オプションは省略可能です。省略した場合SORTプロシージャはDATA=オプションで指定されたデータセットを並べ替えた状態で更新されます。したがって、出力を一時的に作成するためだけにデータを並べ替える必要がある場合は、OUT=オプションと一時SASデータセット名の指定を併せて使う必要があります。
デフォルトでは、SASはBYステートメントの変数の値を昇順で並べ替えます。降順で並べ替えたい場合は、BYステートメントのDESCENDINGオプションを使う必要があります。

#

以下のプログラムは、BYステートメントのDESCENDINGオプションを使い、一時データセットback8をまず「gender」で降順、次に「age」で昇順に並べ替えるようにしています。

proc sort data = back8 out = srtd_back8;
  by descending gender age;
run;

title "First 5 sorted observations for gender  = 1";
proc print data = srtd_back8 (obs = 5);
  var gender age subj v_date birth;
run;

title "First 5 sorted observations for gender  = 2";
proc print data = srtd_back8 (firstobs = 57 obs = 62);
  var gender age subj v_date birth;
run;
title ;
SAS 出力

First 5 sorted observations for gender = 1

OBS gender age subj v_date birth
1 2 -23.1534 410097 04/24/96 06/14/19
2 2 -22.6795 420074 09/07/95 05/07/18
3 2 -22.6466 520007 08/13/93 03/31/16
4 2 -22.2438 310102 02/12/96 05/06/18
5 2 -22.1781 420112 12/17/96 02/15/19

First 5 sorted observations for gender = 2

OBS gender age subj v_date birth
57 2 26.5479 410006 09/09/93 02/28/67
58 2 26.5863 510051 01/20/95 06/26/68
59 2 26.6110 410091 02/14/96 07/12/69
60 2 26.7452 210100 05/06/96 08/14/69
61 2 26.7507 210006 05/13/93 08/19/66
62 2 26.8438 220036 08/08/95 10/10/68

プログラムを開き、FIRSTOBSとOBSのデータセットオプションを削除して全データセットを出力することで、データセットが所望の順序で並べ替えられていることを確認してください。BYステートメントに複数の変数が含まれる場合、DESCENDINGオプションはその直後の変数にのみ適用されることに注意してください。BYステートメントでgenderとageの間にDESCENDINGを追加し、プログラムを再実行して動作を確認してみてください。

演習#

  1. データセットsashelp.heartから一時SASデータセットheartを作成してください。(ライブラリsashelpは、SASに同梱された永久ライブラリです)

  2. PROC CONTENTSを実行してデータセットheartのディスクリプタ部を表示してください。このデータセットにはいくつのオブザベーション(行)と変数(列)がありますか?

  3. データセットオプションのRENAME=オプションを使って、Statusconditionに変更します。PROC CONTENTSの変数の一覧を表示して、名前が変更されたことを確認してください。

  4. データセットheartからサブセットheart_subを作成し、heightweightdiastolicの列のみを含めます。heart_subのオブザベーション(行)と変数(列)はいくつですか?heart_subの最初の5行を出力してくださいす。

  5. データセットheartから、拡張期血圧(diastolic)が90を超える被験者の行をデータセットheart_sub2にサブセットします。何オブザベーションありますか?heart_sub2の最初の5行を出力してください。

  6. データセットheartから、拡張期血圧が90以下で体重が180ポンド以上の被験者の行をデータセットheart_sub3にサブセットします。何オブザベーションありますか?heart_sub3の最初の5行を出力してください。

  7. データセットheartから重度の喫煙者(Smoking_Status = “Heavy (16-25)”)について、weightsystoliccholesterolの列のみを含むサブセットを作成します。このサブセットをheart_subに保存します。このデータセットののオブザベーション(行)と変数(列)はいくつですか?heart_subの最初の5行を出力してください。

  8. データセットheart_subの行を、コレステロール値の降順で並べ替えます。並べ替えたデータセットの最初の5行を出力してください。