stata命令详解

【实战】 stata-挑出最长的句子

2020-01-18  本文已影响0人  Hobbit的理查德

1.背景

有一天,吃完晚饭,郑老师突然严肃地跟我说:

“夫人,我想给学生做口语串词成句的强化训练,所以想从TPO(TOEFL Practice Online)的每篇口语task2的听力文稿中找出其中最长的句子。如果学生能够口头翻译出这些最长的句子,那么就不会再惧怕驾驭其他长度的句子了。”

我:”那你有整理文稿不?多少个TPO?“

郑老师:”有,54个“

我:”你说的长,指的是单词数量,还是字母数量?“

郑老师:”单词数量“

我:”以什么标点作为断句嘞“

郑老师:”句号,问号和感叹号就行。“

我:”好的,我看看吧,应该没问题。“

郑老师:”能挑出长度前三的句子最好了。“

我:”OK“

2.需求

TPO口语听力文稿示例:

听力文稿示例.png

3.思路

  1. 清洗整理对话内容;
  2. 按逗号,问号,感叹号拆分句子;
  3. 计算每个句子的长度;
  4. 宽数据转长数据;
  5. 排序得到每个TPO听力对话里每个句子及其长度;

4.过程

①导入及清洗

*导入excel至stata中,读取TPO-T3工作表
import excel "C:\study\实战\stata\c9450527a8fb1bbc.xlsx", sheet("TPO-T3") 

*保存为TPO3.dta数据
save TPO3,replace

*复制字段C(原文句子)至新字段newC
clonevar newC=C
*将原文句子中换行符删除,不然到时候导出excel时只会读取第一行数据,char(10)表示换行符
replace newC=subinstr(newC,char(10),"",.)

效果如下图:

字段C.png 字段newC.png
*清洗,将原文中含有(woman) ,(women) ,(man) ,Man:,Woman:,M: ,W: ,Man:,Woman: ,Woman:,(man):,(woman):,(man)删除,并将...替换成.
replace newC=subinstr(newC,"(woman) ","",.)
replace newC=subinstr(newC,"(women) ","",.)
replace newC=subinstr(newC,"(man) ","",.)
replace newC=subinstr(newC,"Man:","",.)
replace newC=subinstr(newC,"Woman:","",.)
replace newC=subinstr(newC,"M: ","",.)
replace newC=subinstr(newC,"W: ","",.)
replace newC=subinstr(newC,"Man:","",.)
replace newC=subinstr(newC,"Woman: ","",.)
replace newC=subinstr(newC,"Woman:","",.) 
replace newC=subinstr(newC,"(man):","",.) 
replace newC=subinstr(newC,"(woman):","",.) 
replace newC=subinstr(newC,"(man)","",.)
replace newC=subinstr(newC,"...",".",.) 

*有的TPO最开始还有一个空格,将句子的第一个空格删掉
gen newC_first=substr(newC,1,1)
replace newC=subinstr(newC," ","",1) if newC_first==" "

效果如下:

再次字段newC.png

②句子拆分

*根据英文句号拆分句子,字段前缀为sen_fs_
split newC,gen(sen_fs_) parse(.)

句号拆分后效果:


句号拆分.png
*查看第一条拆分后这些字段的结果
l sen_fs_1-sen_fs_23 in 1
句号拆分后.png
*对生成的字段名为sen_fs_的变量进行循环处理,将这些变量再次根据问号生成前缀为 原字段名_qu_ 的新字段
foreach i of varlist sen_fs_*{
split `i' if `i'!="",gen(`i'_qu_) parse(?)
}

*同理,对生成的字段名为sen_fs_*_qu_*(*表示通配符)的变量进行循环处理,将这些变量再次根据感叹号生成前缀为 原字段名_ex_ 的新字段
foreach i of varlist sen_fs_*_qu_* {
split `i' if `i'!=""&`i'!=" ",gen(`i'_ex_) parse(!)
}

问号及感叹号拆分后效果:

*查看第一条拆分后这些字段的结果
l sen_fs_1_qu_1_ex_1-sen_fs_23_qu_1_ex_1 in 1
问号&感叹号拆分.png

③句子长度计算

*对拆分后的每个句子进行长度计算,思路是将文本长度-(将文本中空格删掉后的长度)+1,得到拆分后的每个句子长度,并生成相应的字段名为 len_原字段 的新字段 
foreach i of varlist sen_fs_*_qu_*_ex_* {
gen len_`i'=strlen(`i')-strlen(subinstr(`i'," ","",.)) + 1
}
*另存数据为TPO-T3
save TPO-T3,replace

长度计算结果示例:

*查看第一条拆分后的第一个句子的内容及句子长度
l sen_fs_1_qu_1_ex_1 len_sen_fs_1_qu_1_ex_1 in 1
句子长度示例.png

④宽数据转长数据

*开始进行宽数据变为长数据
*调用刚才保存的TPO-T3数据
use TPO-T3,clear

*批量将字段名为 sen_fs_*_qu_*_ex_* (即拆分后的每个句子)的字段重新命名,前缀为sentence_,后接数字
local num = 1
foreach i of varlist sen_fs_*_qu_*_ex_* {
local newname = "sentence"+"`num'"
rename `i' `newname'
local num = `num' + 1
     }
*同理,批量将字段名为 len_sen_fs_*_qu_*_ex_*(即拆分后的每个句子的长度)的字段重新命名,前缀为len_sentence_,后接数字
local num = 1
foreach i of varlist len_sen_fs_*_qu_*_ex_* {
local newname = "len_sentence"+"`num'"
rename `i' `newname'
local num = `num' + 1
     }
*将宽数据转为长数据,即原来是一条数据中包括拆分后的n个句子(字段),转换后,变成1个字段的n条数据
reshape long sentence len_sentence,i(A) j(sen_num)

*删除句子长度为1,即拆分后的句子为空的case
drop if len_sentence==1

⑤排序及导出

*将字段A重命名为TPO
rename A TPO

*根据TPO升序和句子长度降序进行排序
gsort TPO -len_sentence

*对每个TPO,生成字段num算出每个TPO的句子个数和句子长度排名
by TPO:gen num=_N
by TPO:gen rank=_n

*字段添加变量标签
label var num "tpo句子个数"
label var rank "tpo内句子长度排名"
label var C "原文"
label var sentence "句子"
label var len_sentence "句子长度"

*对原文字段C删掉换行符,便于导出
replace C=subinstr(C,char(10),"",.)

*导出excel数据,并以变量标签作为第一列字段名
export excel TPO C sentence num rank len_sentence using "C:\study\实战\stata\TPO-T3_长度前3.xlsx", firstrow(varlabels) replace

5.结果

最后导出的excel结果如图:

结果.png

这样,郑老师不仅可以知道每个TPO的最长的句子,也可以挑出所有TPO中最长的句子,或者任意选取长度前n的句子啦~~

6.最后

郑老师:哇哦,我原本还打算自己肉眼看,预计两三天才完成呢~

我:郑老师,以后有类似的机械的活儿请告诉我好嘛~

郑老师:没问题😁

上一篇下一篇

猜你喜欢

热点阅读