SASマクロ データ変換

【SAS】法人名(社名)から法人格を削除するマクロ(TRANWRD、SUBSTR)

hojin_del_hojinkaku

1. サンプルデータ

サンプルとして、以下のように、法人リストを用意します。

data hojin_list;
	infile datalines dlm="," dsd missover;
	input hojin_name:$200.;
datalines;
日本郵船株式会社
株式会社Mizkan J plus Holdings
公益社団法人福岡医療団
社団医療法人 啓愛会
一般社団法人 北陸地区信用金庫協会
兵庫県弁護士協同組合
学校法人 藤田学園
一般財団法人東北電気保安協会
社会医療法人蘇西厚生会
公益社団法人福岡医療団
田中貴金属労働組合
医療法人社団 友愛病院会
東京海上日動調査サービス共済組合
社会医療法人財団白十字会
オカムラグループ健康保険組合
日本ヒューレット・パッカード合同会社
社団医療法人 啓愛会
;
run;

データセットを開くと以下のようになります。
hojin

 

2. 展開例

以下は展開例になります。
引数hojinkakuに、削除対象となる法人格を指定する場合は、以下のように、一旦、別のマクロhojinkakuにまとめると良いでしょう。

%macro hojinkaku;
/*--------------------------------------------------
法人格
--------------------------------------------------							
法人の種類			漢字略語
--------------------------------------------------*/
株式会社			(株)		
有限会社			(有)		
合名会社			(名)		
合資会社			(資)		
合同会社			(同)		
医療法人			(医)		
医療法人社団				
医療法人財団				
社会医療法人
社団医療法人	
財団法人			(財)		
一般財団法人			(一財)		
公益財団法人			(公財)		
社団法人			(社)		
一般社団法人			(一社)		
公益社団法人			(公社)		
宗教法人			(宗)		
学校法人			(学)		
社会福祉法人			(福)
更生保護法人					
相互会社			(相)		
特定非営利活動法人		(特非)
独立行政法人			(独)	
地方独立行政法人		(地独)
弁護士法人			(弁)		
有限責任中間法人		(中)	
無限責任中間法人			
行政書士法人			(行)		
司法書士法人			(司)		
税理士法人			(税)	
国立大学法人			(大)			
公立大学法人				
農事組合法人					
管理組合法人					
社会保険労務士法人				
/*--------------------------------------------------				
営業所名称			漢字略語
--------------------------------------------------*/
営業所				(営)
出張所				(出)
/*--------------------------------------------------
事業名称			漢字略語
--------------------------------------------------*/
連合会				(連)
共済組合			(共済)
協同組合			(協組)
生命保険			(生命)
海上火災保険			(海上)
火災海上保険			(火災)
健康保険組合			(健保)
国民健康保険組合		(国保)
国民健康保険団体連合会		(国保連)
社会保険診療報酬支払基金	(社保)
厚生年金基金			(厚年)
従業員組合			(従組)
労働組合			(労組)
生活協同組合			(生協)
食糧販売協同組合		(食販協)
国家公務員共済組合連合会        (国共連)
農業協同組合連合会		(農協連)
経済農業協同組合連合会	        (経済連)
共済農業協同組合連合会	        (共済連)
漁業協同組合			(漁協)
漁業協同組合連合会		(漁連)
公共職業安定所			(職安)
社会福祉協議会			(社協)
特別養護老人ホーム		(特養)
有限責任事業組合	        (責)
/*--------------------------------------------------
その他				漢字略語
--------------------------------------------------*/
特例財団法人			(特財)
特例社団法人			(特社)
協業組合			(業)
%mend hojinkaku;
%del_hojinkaku(indata=hojin_list, old=hojin_name, new=hojin_name2, hojinkaku=%hojinkaku, outdata=hojin_list2);

 

3. 出力結果

以下のように、法人格の削除された法人名hojin_name2が作成されました。
hojin_del_hojinkaku

4. 参考プログラム

以下は、参考プログラムになります。
右上のコピーボタンを押せば、プログラム全体をコピーできます。

%macro del_hojinkaku(indata=, old=, new=, hojinkaku=, outdata=);
%put --------------------------------------------------;
%put del_hojinkaku;
%put 法人格の削除;
%put &=indata;		/*入力データセット名を指定する*/
%put &=old;			/*法人格削除前の変数名を指定(省略不可、複数指定可、略記法不可、指定した変数はドロップせず保持する)*/
%put &=new;			/*法人格削除後の変数名を指定(省略不可、複数指定する場合はoldと並び順を対応させること、oldと同じ変数名を指定した場合は上書きする)*/
%put &=hojinkaku;	/*削除したい法人格を指定する(スペース区切りで複数指定可)*/
%put &=outdata;		/*出力データセット名を指定する*/
%put --------------------------------------------------;

	/*データの読込み*/
	data _del_hojinkaku_temp;
		format &old.;
		keep &old.;
		set &indata.;
	run;

	/*変数情報の取得*/
	proc contents data=_del_hojinkaku_temp
				  out =_del_hojinkaku_cont
				  noprint;
	run;
	proc sort data=_del_hojinkaku_cont;
		by varnum;
	run;

	/*oldのマクロ変数化*/
	data _null_;
		set _del_hojinkaku_cont;
		call symputx("num_old", _n_);
		call symputx(cats("old", _n_), name);
		call symputx(cats("old_len", _n_), length); 
	run;

	/*newのマクロ変数化*/
	%let num_new = %sysfunc(countw(%superq(new),, s));
	%do __i=1 %to &num_new.;
		%let new&__i = %sysfunc(strip(%qscan(&new., &__i,, s))) ;
	%end;

	/*変数の数の対応チェック*/
	%if &num_old. ne &num_new. %then %put ERROR:パラメータoldとnewに指定した変数の数が異なります。;

	/*上書きする変数はWARNINGを出す*/
	%do __i=1 %to &num_old.;
		%if &&old&__i.. = &&new&__i.. %then %put WARNING:法人格削除の前後で同一変数名を指定しているので上書きします。 old&__i.=&&old&__i.. new&__i.=&&new&__i..; 
	%end;

	/*法人格のマクロ変数化*/
	%let num_hojin = %sysfunc(countw(%superq(hojinkaku),, s));
	%do __i=1 %to &num_hojin.;
		%let hojin&__i = %sysfunc(strip(%qscan(&hojinkaku., &__i,, s))) ;
	%end;

	/*法人格の削除*/
	data &outdata.;
		set &indata.;

		/*新変数の長さの定義*/
		length
			%do __i=1 %to &num_old.;
				org_&&old&__i..	/*チェック用一時変数*/

				&&new&__i..
				bfr_&&new&__i.. 
				aft_&&new&__i.. 
				$&&old_len&__i...
			%end;
		;

		/*法人格の削除*/
		%do __i=1 %to &num_old.;

			/*オリジナル変数値をチェック用一時変数に格納*/
			org_&&old&__i..=&&old&__i..;

			/*新規変数にオリジナル変数値を格納*/
			&&new&__i..=&&old&__i..;
	
			do until(chk_cnt&__i. = 0);
				%do __j=1 %to &num_hojin.;

					%if &__j.=1 %then %do;

						/*法人格削除*/
						bfr_&&new&__i..=ktrim(kleft(tranwrd(&&new&__i.., "&&hojin&__j..", "")));
						
						/*データ値の法人格が半角になっている可能性も考えて、以下の処理も加える*/
						bfr_&&new&__i..=ktrim(kleft(tranwrd(bfr_&&new&__i.., kpropcase(kpropcase("&&hojin&__j..",'full-katakana, half-katakana'),'full-alphabet, half-alphabet'), "")));

					%end;	
					%else %do;
						aft_&&new&__i..=ktrim(kleft(tranwrd(&&new&__i.., "&&hojin&__j..", "")));
						aft_&&new&__i..=ktrim(kleft(tranwrd(aft_&&new&__i.., kpropcase(kpropcase("&&hojin&__j..",'full-katakana, half-katakana'),'full-alphabet, half-alphabet'), "")));

						/*
						「医療法人」と「医療法人社団」など、互いに内包する文字列を含む場合もあるので、
						削除後の文字列の長さが最小になる変換のみ残す
						*/
						if length(bfr_&&new&__i..) > length(aft_&&new&__i..) then bfr_&&new&__i..=aft_&&new&__i..;
					%end;
				%end;

				/*最終的に、削除後の文字列長さが最小となる変数値を格納する*/
				&&new&__i..=ktrim(kleft(bfr_&&new&__i..));

				/*法人格が含まれている場合は再ループ*/
				chk_cnt&__i. = 0;
				%do __j=1 %to &num_hojin.;
					if kindex(ktrim(kleft(&&new&__i..)), "&&hojin&__j..")  > 0 then chk_cnt&__i. + 1;
				%end;
			end;

			/*
			英文以外のスペースを詰める
			BLUE EARTH		→ BLUE EARTH
			ブルー アース	→ ブルーアース
			*/
			bfr_space&__i.=0;
			aft_space&__i.=0;
			if not missing(&&new&__i..) then do;
				do until(bfr_space&__i.=0 and aft_space&__i.=0);

					/*スペースのある位置を取得*/
					if 		kindex(ktrim(kleft(&&new&__i..)), " ")  > 0 then space&__i.=kindex(ktrim(kleft(&&new&__i..)), " ");
					else if kindex(ktrim(kleft(&&new&__i..)), " ") > 0 then space&__i.=kindex(ktrim(kleft(&&new&__i..)), " ");
					else space&__i.=0;

					if space&__i. > 0 then do;
						/*スペースの前後の1文字を取得し、全角→半角化し、アルファベット有無の判定をする*/
						bfr_space&__i.=notalpha(ktrim(kleft(kpropcase(ksubstr(&&new&__i.., space&__i.-1, 1),'full-alphabet, half-alphabet'))));
						aft_space&__i.=notalpha(ktrim(kleft(kpropcase(ksubstr(&&new&__i.., space&__i.+1, 1),'full-alphabet, half-alphabet'))));
						
						/*スペースの前後がアルファベット以外ならスペースを削除する*/
						if bfr_space&__i. > 0 or aft_space&__i. > 0 then do;
							&&new&__i..=cats(ksubstr(&&new&__i.., 1, space&__i.-1), ksubstr(&&new&__i.., space&__i.+1));
						end;
					end;
					else do;
						bfr_space&__i.=0;
						aft_space&__i.=0;
					end;
				end;
			end;

			/*変換されたレコードのみチェック*/
			if org_&&old&__i.. ne &&new&__i.. then do;

				/*変換チェック(最大20レコード分)*/
				cnt&__i. + 1;
				if cnt&__i. <=20 then do;
					if cnt&__i.=1 then do;
						put "WARNING:変換チェック(最大20レコード分):&&new&__i..";
						put " ";
					end;
					put "WARNING:変換前:" (org_&&old&__i..)(=);
					put "WARNING:変換後:" (&&new&__i..)(=);
					put " ";
				end;

			end;
		%end;

		/*不要な一時変数のドロップ*/
		drop
			%do __i=1 %to &num_old.;
				org_&&old&__i..
				bfr_&&new&__i..
				aft_&&new&__i..
				bfr_space&__i.
				aft_space&__i.
				chk_cnt&__i.
				space&__i.
				cnt&__i.
			%end;
		;
	run;

%mend del_hojinkaku;