【实战】 stata-挑出最长的句子
2020-01-18 本文已影响0人
Hobbit的理查德
1.背景
有一天,吃完晚饭,郑老师突然严肃地跟我说:
“夫人,我想给学生做口语串词成句的强化训练,所以想从TPO(TOEFL Practice Online)的每篇口语task2的听力文稿中找出其中最长的句子。如果学生能够口头翻译出这些最长的句子,那么就不会再惧怕驾驭其他长度的句子了。”
我:”那你有整理文稿不?多少个TPO?“
郑老师:”有,54个“
我:”你说的长,指的是单词数量,还是字母数量?“
郑老师:”单词数量“
我:”以什么标点作为断句嘞“
郑老师:”句号,问号和感叹号就行。“
我:”好的,我看看吧,应该没问题。“
郑老师:”能挑出长度前三的句子最好了。“
我:”OK“
2.需求
TPO口语听力文稿示例:
听力文稿示例.png- 从54段这样的对话中挑出最长或者长度前三的句子;
- 不需要前面的Man和Woman;
- 以单词数量计算长度;
- 句号,问号和感叹号作为断句标志;
3.思路
- 清洗整理对话内容;
- 按逗号,问号,感叹号拆分句子;
- 计算每个句子的长度;
- 宽数据转长数据;
- 排序得到每个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
- 说明:54个TPO中,根据句号拆分出最多23个句子;
- 另外,根据句号拆分后,每个句子里还有问号和感叹号需要进一步拆分。
*对生成的字段名为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.最后
郑老师:哇哦,我原本还打算自己肉眼看,预计两三天才完成呢~
我:郑老师,以后有类似的机械的活儿请告诉我好嘛~
郑老师:没问题😁