创建一个表格,显示两个相交变量的公共值的数量

时间:2014-03-25 18:18:38

标签: spss

我想创建一个表,使得行和列是我的变量,每个单元格显示两个相交变量的公共值的数量。

例如,我有以下带有值的变量。

 x    y    z
---  ---  ---
 *    b    #
 g    #    i
 #    *    l
 +    k    
      m    

请注意,*和#在某些变量中很常见。 x和z之间只有一个共同的值(即#),因此单元格(x,z)将为1。完整的表格如下所示。

    x    y    z
   ---  ---  ---
x | 4    2    1
y | 2    5    1
z | 1    1    3

如何使用SPSS进行操作以及描述此问题的关键字是什么。

3 个答案:

答案 0 :(得分:2)

有一种使用宏语言的解决方案。

测试数据

*** Set the work directory.
cd "C:\temp".


*** Define the list of variable names.
* You can make it using Utilities / Variables... command.
define !varl() x y z !end.


*** Generate the test data.
data list free
 /x (a1) y (a1) z (a1).
begin data
* b #
g # i
# * l
+ k ""
"" m ""
end data.

save out "data.sav".


*** Open each variable in a new data file, drop blanks, sort and save.
define !get_sort_save(x = !cmdend)
!do !var !in (!x)

get "data.sav"
 /keep !var.

sel if !var <> "".

sort cases by !var.

save out !quote(!con(!var, ".sav")).

!doend
!end.


* Run.
!get_sort_save x = !varl.



*** Match each variable with all other variables and count the matched cases.
define !match_count(x = !cmdend)

!do !var1 !in (!x)

get !quote(!con(!var1, ".sav"))
 /ren !var1 = id.

!do !var2 !in (!x)

match files
 /file = *
 /table = !quote(!con(!var2, ".sav"))
 /ren !var2 = id
 /in !var2
 /by id.

!doend

agg out *
 /!x = sum(!x).

form !x (f8).

save out !quote(!con(!var1, "_n.sav")).

!doend
!end.


* Run.
!match_count x = !varl.


*** Add the counts.
define !add(x = !cmdend)
add files
!do !var !in (!x)
 /file = !quote(!con(!var, "_n.sav"))
!doend.
!end.


* Run.
!add x = !varl.

list.

结果是

       x        y        z

       4        2        1
       2        5        1
       1        1        3

Number of cases read:  3    Number of cases listed:  3

真实数据

这是在真实数据上运行的代码。数据必须保存在数据文件中。代码中有三个位置需要进行更改。它们标有TASK1,TASK2和TASK3。

*** TASK1 - set the work directory - the directory where the data file is saved.
cd "C:\temp".


*** TASK2 -  Define the list of variable names.
define !varl() x y z !end.


*** Open each variable in a new data file, drop blanks, sort and save.
define !get_sort_save(x = !cmdend)
!do !var !in (!x)

*** TASK3 - change the file name.
get "data.sav"
 /keep !var.

sel if !var <> "".

sort cases by !var.

save out !quote(!con(!var, ".sav")).

!doend
!end.


* Run.
!get_sort_save x = !varl.



*** Match each variable with all other variables and count the matched cases.
define !match_count(x = !cmdend)

!do !var1 !in (!x)

get !quote(!con(!var1, ".sav"))
 /ren !var1 = id.

!do !var2 !in (!x)

match files
 /file = *
 /table = !quote(!con(!var2, ".sav"))
 /ren !var2 = id
 /in !var2
 /by id.

!doend

agg out *
 /!x = sum(!x).

form !x (f8).

save out !quote(!con(!var1, "_n.sav")).

!doend
!end.


* Run.
!match_count x = !varl.


*** Add the counts.
define !add(x = !cmdend)
add files
!do !var !in (!x)
 /file = !quote(!con(!var, "_n.sav"))
!doend.
!end.


* Run.
!add x = !varl.

list.

答案 1 :(得分:1)

这是一个挑战 - 所以这是我尝试以合理的格式编写代码。首先,让我们创建一个看起来像你的数据集。

DATA LIST FREE / x y z (3A1).
BEGIN DATA
 *    b    #
 g    #    i
 #    *    l
 +    k    ""
 ""   m    ""
END DATA.

现在我做的是制作一个符号列表,然后是一个虚拟变量信号,如果该符号包含在原始变量中。

VARSTOCASES /MAKE V from x TO z /INDEX OrigVar (V).
SORT CASES BY V OrigVar.
CASESTOVARS /ID = V /VIND ROOT = "D" /INDEX = OrigVar. 

您将看到数据现在如下所示:

V Dx Dy Dz 
- -- -- --
*  1  1  0 
#  1  1  1 
+  1  0  0 
b  0  1  0 
g  1  0  0 
i  0  0  1 
k  0  1  0 
l  0  0  1 
m  0  1  0

现在,如果您将DxDy相乘,然后将计算两个集合交集的列相加。在这里,我创建一个宏来轻松计算列表中的所有乘法。 (不幸的是,你不能在这里使用TO约定,你需要在这个宏上列出你的使用应用程序的所有25个变量。)

DEFINE !PairInter (!POSITIONAL = !CMDEND).
!DO !I !IN (!1)
!DO !J !IN (!1)
  COMPUTE !CONCAT(!I,"_",!J) = !I*!J.
  FORMATS !CONCAT(!I,"_",!J) (F3.0).
!DOEND
!DOEND
!ENDDEFINE.

!PairInter Dx Dy Dz.

您将看到现在有一​​个变量列表Dx_Dx Dx_Dy Dx_Dz Dy_Dx ..... Dz_Dz,它们是这些变量的完整交互集。我故意写了多余的交互,因为它使得表格在以后变得更容易(尽管我可能建议在显示表格时只显示下半部分)。

所以现在如果我们对列进行求和,我们将得到每个集合的基数及其交集。在这里,我使用LAG并将最终值保留在数据集中。

DO REPEAT D = Dx_Dx TO Dz_Dz.
  IF ($casenum<>1) D = LAG(D) + D.
END REPEAT.
COMPUTE Order = $casenum.
SORT CASES BY Order (D).
SELECT IF ($casenum = 1).
MATCH FILES FILE = * /DROP V TO Dz Order.
EXECUTE.

现在,您可以编写MATRIX过程来重塑数据集并以更好的格式打印出表格。这里我FLIP数据集,然后获取原始变量名称。

STRING I (A1).
COMPUTE I = "I".
FLIP /NEWNAMES = I.
RENAME VARIABLES (CASE_LBL = V).
COMPUTE V = CHAR.SUBSTR(V,LENGTH(V)).
EXECUTE.

MATRIX.
GET I /FILE = * /VARIABLE = I.
GET V /FILE = * /VARIABLE = V.
COMPUTE I2 = RESHAPE(I,3,3).
COMPUTE V2 = V(1:3).
PRINT I2 /RNAMES =V2 /CNAMES = V2.
END MATRIX.

然后打印的MATRIX语句会读取您想要的交叉表。

Run MATRIX procedure: 

I2 
   x  y  z 
x  4  2  1 
y  2  5  1 
z  1  1  3 

------ END MATRIX -----

我把它变成了一个宏,可用here。定义宏后,您只需运行

即可

!InterSet x y z.

它将打印表格。

答案 2 :(得分:1)

这是一个简单的Python解决方案。它会创建一个包含计数的数据透视表。

DATA LIST FREE / x (A1) y (A5) z (A8).
BEGIN DATA
 *    b    #
 g    #    i
 #    *    l
 +    k    ""
 ""   m    ""
END DATA.

begin program.
import spss, spssaux, spssdata

alldata = spssdata.Spssdata(names=False).fetchall()
nvars = len(alldata[0])
ncases = len(alldata)
vnames = [spss.GetVariableName(i) for i in range(nvars)]
empty = set([''])
varsets = {}
for v in range(nvars):
    varsets[v] = set([alldata[i][v].strip() for i in range(ncases)]).difference(empty)
rows = []
for v1 in range(nvars):
    counts = []
    for v2 in range(nvars):
        counts.append(len(varsets[v1].intersection(varsets[v2])))
    rows.append(counts)
spss.StartProcedure("ValuesInCommon")
table = spss.BasePivotTable("Values in Common", "COMMON")
table.SetDefaultFormatSpec(spss.FormatSpec.Count)
table.SimplePivotTable(rowdim = "Variable",
    rowlabels=vnames,
    coldim="Variables ",
    collabels=vnames,
    cells=rows)
spss.EndProcedure()
end program.