「STATS CARTPROD」拡張バンドルをインストールすると、これを行うことができます。この拡張機能を使用すると、外部結合を作成するための中間ステップとしてデカルト積を作成できます。
SPSS 22 以降、プログラム メニュー Extra->Extension Bundles->Install and Download extension bundles から直接ダウンロードできます。ここから手動でダウンロードしてインストールすることもできます
。動作させるために「Python Essentials for SPSS」をインストールしました。
*** create the example data.
DATA LIST FREE / classnbr1 (F1) fact1 (A1).
BEGIN DATA
1 A
1 D
2 A
3 B
END DATA.
DATASET NAME data1.
DATA LIST FREE / classnbr2 (F1) fact2 (A2).
BEGIN DATA
1 XX
1 XY
3 ZZ
END DATA.
DATASET NAME data2.
「STATS CARTPROD」拡張機能を使用しているときに、変数名に大文字を使用すると問題が発生しました。「classnbr」が両方のデータセットで異なる変数名を持つことも重要です。
*** create cartesian product using the STATS CARTPROD extension.
DATASET ACTIVATE data1.
STATS CARTPROD INPUT2=data2
VAR1=classnbr1 fact1 VAR2=classnbr2 fact2
/SAVE OUTFILE="C:\MY FOLDER\cardprod.sav" DSNAME = cart.
EXECUTE.
*** create an equi join.
SELECT IF classnbr1 = classnbr2.
EXECUTE.
DELETE VARIABLES classnbr2.
ここで、data2 に一致しないケースを含めます。
*** create left outer join
* assuming both data sets are ordered by classnbr1 and fact1
ADD FILES
/FILE = cart
/FILE = data1
/BY classnbr1 fact1.
EXECUTE.
DATASET NAME outer_join.
DATASET ACTIVATE outer_join.
COMPUTE select=1.
IF (length(fact2)=0 AND classnbr1=LAG(classnbr1) AND fact1=LAG(fact1)) select=0.
EXECUTE.
SELECT IF select = 1.
EXECUTE.
DELETE VARIABLES select.
ただし、非常に大きなデータ セットを使用すると、問題が発生する可能性があります。その場合、デカルト積は巨大になります。
この影響を少し軽減するために、デカルト積を生成する前に、対応する他のデータ セットに一致しないデータ セットからすべてのケースを削除できます。
これは、それを行う方法です:
*** create the example data.
*** (I added an additional case to the second data set, which will be deleted
in the result, since it has no match in the first data set)
DATA LIST FREE / classnbr1 (F1) fact1 (A1).
BEGIN DATA
1 A
1 D
2 A
3 B
END DATA.
DATASET NAME data1.
DATA LIST FREE / classnbr2 (F1) fact2 (A2).
BEGIN DATA
1 XX
1 XY
3 ZZ
4 XY
END DATA.
DATASET NAME data2.
*** select cases who (don't) have a matching correspondent in the other dataset
** Create a list of unique key values of data set data2
** (In this Example the key Value is classnbr2).
DATASET ACTIVATE data2.
DATASET COPY data2_keylist.
DATASET ACTIVATE data2_keylist.
* Assuming the data set is already sorted by the key value.
* Mark the first occurance of every key kalue in the data set.
COMPUTE list = 1.
IF classnbr2 = LAG(classnbr2) list = 0.
SELECT IF list=1.
EXECUTE.
* Delete all variables except the (now unique) key value
MATCH FILES
/FILE *
/KEEP classnbr2.
EXECUTE.
** Match the list of data2 key values to data1 in order to mark
** which cases of data1 have at least one correspondent case in data 2.
DATASET ACTIVATE data1.
MATCH FILES
/FILE *
/TABLE data2_keylist
/RENAME classnbr2=classnbr1
/IN data2
/BY classnbr1.
EXECUTE.
** Remove cases from data1 who don't have a correspondent in data2
** and store them in another dataset, because we need to add them later.
DATASET COPY date1_nomatch.
SELECT IF data2=1.
EXECUTE.
DATASET ACTIVATE date1_nomatch.
SELECT IF data2=0.
EXECUTE.
** Now doing the same for the other data set.
** Create a list of unique key values of data set data1
** (In this Example the key Value is classnbr1).
DATASET ACTIVATE data1.
DATASET COPY data1_keylist.
DATASET ACTIVATE data1_keylist.
* Assuming the data set is already sorted by the key value.
* Mark the first occurance of every key kalue in the data set.
COMPUTE list = 1.
IF classnbr1 = LAG(classnbr1) list = 0.
SELECT IF list=1.
EXECUTE.
* Delete all variables except the (now unique) key value
MATCH FILES
/FILE *
/KEEP classnbr1.
EXECUTE.
** Match the list of data2 key values to data1 in order to mark
** which cases of data1 have at least one correspondent case in data 2.
DATASET ACTIVATE data2.
MATCH FILES
/FILE *
/TABLE data1_keylist
/RENAME classnbr1=classnbr2
/IN data1
/BY classnbr2.
EXECUTE.
** Remove cases from data1 who don't have a correspondent in data2.
SELECT IF data1=1.
EXECUTE.
*** create a cartesian product of the two reduced datasets.
DATASET ACTIVATE data1.
STATS CARTPROD INPUT2=data2
VAR1=classnbr1 fact1 VAR2=classnbr2 fact2
/SAVE OUTFILE="C:\MY FOLDER\cardprod.sav" DSNAME = outer_join.
EXECUTE.
*** create an equi join.
SELECT IF classnbr1 = classnbr2.
EXECUTE.
DELETE VARIABLES classnbr2.
*** create left outer join by adding the cases from date1_nomatch.
DATASET ACTIVATE outer_join.
ADD FILES
/FILE = *
/FILE = date1_nomatch
/BY classnbr1 fact1
/DROP data2.
EXECUTE.
* Some cleaning up.
DATASET CLOSE data1_keylist.
DATASET CLOSE date1_nomatch.
DATASET CLOSE data2_keylist.