近期因为在为国家的一个大型调查做抽样工作,前两个阶段每个调查点要抽3个乡镇街道,每个街道要抽2个村居委。按照国家的培训,在SPSS中按照特定的操作流程,采用Simple_systemic(简单系统随机)抽样方法,国家为了避免作弊便于后期核查,需要记录下抽样的种子数,所以按照界面不停点点,一次抽样要折腾上10分钟,然后10个调查点×3个乡镇×2个村居委=60个样本,然后每次抽样过程中还有不满意要重抽……感觉整个人都要不好了。
为了缓解日益恶化的腕管综合征和日益恶化的视力,我开始寻求各种可以提(tou)高(lan)效(sheng)率(shi)的方法。
首先是用SAS和Python分别编了抽样的程序,但是用同样的种子怎么也重复不出SPSS的抽样结果。
其他程序指望不上了,只能在SPSS一棵树上吊死了。于是我又把目光转向了Syntex(语法)模块,每次操作完的时候,点击“粘帖”,SPSS就会很贴心的给你一段程序,改一下种子号(/SIZE VALUE=),Ctrl+A(全选),Ctrl+R(运行),3步操作,简单搞定,天无绝人之路嘛!
* 抽样向导.
CSPLAN SAMPLE
/PLAN FILE='D:\抽样\stage2.csplan'
/PLANVARS SAMPLEWEIGHT=SampleWeight_Final_
/PRINT PLAN
/DESIGN STRATA=code CLUSTER=code1
/METHOD TYPE=SIMPLE_SYSTEMATIC ESTIMATION=DEFAULT
/SIZE VALUE=3
/STAGEVARS INCLPROB(InclusionProbability_1_) CUMWEIGHT(SampleWeightCumulative_1_)
WEIGHT(SampleWeight_1_).
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=101
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果.sav'
/PRINT SELECTION.
但用到后面发现弊病了,第一,待抽样的SPSS文件必须保持打开,当前活动状态;每次抽样要手动修改种子数,抽完后生成的文件(D:\抽样\抽样结果101.sav)要关闭了,才能进行下一次抽样,而抽样结果是否满意必须要每次打开这个文件。于是程序跑的过程中,抽样结果文件却要不断打开和关闭,感觉我的腕管综合征又要复发了。
接下来需要解决这样两个问题,1.如何减少频繁修改种子号(一次跑出10个结果);2.如何把结果汇总到一个文件,只打开查看一次。基于这个目的,我对程序进行了野蛮改造,暂时不考虑运用宏或者循环语句,需要重设种子数的程序模块,我直接采用粘帖复制的处理方式,简单粗暴,但不得不说很好用。另外为了把所有的抽样结果汇总到一个文件里,我先把每个种子数的抽样结果分别导出,然后合并到了一个空库里(还得手工新建一个空库),最后形成了以下这么个程序:
* 抽样向导.
CSPLAN SAMPLE
/PLAN FILE='D:\抽样\stage2.csplan'
/PLANVARS SAMPLEWEIGHT=SampleWeight_Final_
/PRINT PLAN
/DESIGN STRATA=code CLUSTER=code1
/METHOD TYPE=SIMPLE_SYSTEMATIC ESTIMATION=DEFAULT
/SIZE VALUE=3
/STAGEVARS INCLPROB(InclusionProbability_1_) CUMWEIGHT(SampleWeightCumulative_1_)
WEIGHT(SampleWeight_1_).
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=101
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果101.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=102
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果102.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=103
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果103.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=104
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果104.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=105
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果105.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=106
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果106.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=107
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果107.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=108
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果108.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=109
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果109.sav'
/PRINT SELECTION.
CSSELECT
/PLAN FILE='D:\抽样\stage2.csplan'
/CRITERIA STAGES=1 SEED=110
/CLASSMISSING EXCLUDE
/SAMPLEFILE OUTFILE='D:\抽样\抽样结果110.sav'
/PRINT SELECTION.
*合并抽样库.
GET
FILE='D:\抽样\抽样结果.sav'.
DATASET NAME 数据集2 WINDOW=FRONT.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果101.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果102.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果103.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果104.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果105.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果106.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果107.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果108.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果109.sav'.
EXECUTE.
DATASET ACTIVATE 数据集2.
ADD FILES /FILE=*
/FILE='D:\抽样\抽样结果110.sav'.
EXECUTE.
整个程序的操作流程是,国家系统里导出数据(CSV)--把待抽样的乡镇信息拷到SPSS数据库里--修改种子数等参数--Ctrl+R。运行过程很流畅,最后出来的SPSS结果文件里也如期并入了10次的抽样结果,但总觉得哪里差了点,如果我想一次抽20次呢?另外再复制10次真的很蠢,而且每次维护种子数真是一种灾难。
于是我继续在百度中上下求索。要想简化程序,要么就是用循环语句,要么就是用宏,在国内的论坛里逛了一圈,从”DO REPEAT“到”LOOP“各种尝试都宣告失败,兜兜转转一圈,最后发现在SPSS的16.0及以上版本中能够通过调用Python来解决这个问题,上述的粘帖复制部分可以用以下程序来替代:
CSPLAN SAMPLE
/PLAN FILE='D:\抽样\stage2.csplan'
/PLANVARS SAMPLEWEIGHT=SampleWeight_Final_
/PRINT PLAN
/DESIGN STRATA=code CLUSTER=code1
/METHOD TYPE=SIMPLE_SYSTEMATIC ESTIMATION=DEFAULT
/SIZE VALUE=3
/STAGEVARS INCLPROB(InclusionProbability_1_) CUMWEIGHT(SampleWeightCumulative_1_)
WEIGHT(SampleWeight_1_).
begin program.
import spss,spssaux
for i in range(101,111):
spss.Submit("CSSELECT/PLAN FILE='D:\抽样\stage2.csplan'/CRITERIA STAGES=1 SEED=" + str(i) + "/CLASSMISSING EXCLUDE/SAMPLEFILE OUTFILE='D:\抽样\抽样结果" + str(i) + ".sav'/PRINT SELECTION.")
end program.
GET
FILE='D:\抽样\抽样结果.sav'.
DATASET NAME 数据集2 WINDOW=FRONT.
begin program.
import spss,spssaux
for i in range(101,111):
spss.Submit("DATASET ACTIVATE 数据集2.\n ADD FILES /FILE=* /FILE='D:\抽样\抽样结果" + str(i) + ".sav'. \n EXECUTE.")
end program.
跑出来的效果和上一个程序是一样的,但程序的可读性和可维护性大为提高。发现折腾了一大圈,最后还是回到Python上来了,建议国家下次调查别用SPSS做抽样了,用Python也挺好的。
最后总结一下,SPSS的Syntex模块是一个辅助角色,所以在SPSS里的日常还是不停的点点点;此外Python+Syntex尽管能够实现很多的功能,但是句式上存在太多的嵌套,之间还有很多的坑会碰到(比如字符串拼接,传参的类型等等),搞定这些内容以后,你会觉得当初还不如直接用Python了呢。