├── images
├── Alipay.jpg
├── Wechat.jpg
└── onetext
│ ├── figure1.png
│ ├── figure2.png
│ └── figure3.png
├── docs
├── others
│ ├── cheatsheets.pdf
│ └── tutorialbyoscar.pdf
├── otherpage.md
├── log.md
├── myado
│ ├── onetext.md
│ └── oneclick.md
├── chapter-4.md
├── chapter-3.md
├── chapter-1.md
├── chapter-5.md
└── chapter-2.md
├── _coverpage.md
├── _sidebar.md
├── index.html
├── .github
└── workflows
│ └── static.yml
├── README.md
└── LICENSE.md
/images/Alipay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/images/Alipay.jpg
--------------------------------------------------------------------------------
/images/Wechat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/images/Wechat.jpg
--------------------------------------------------------------------------------
/images/onetext/figure1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/images/onetext/figure1.png
--------------------------------------------------------------------------------
/images/onetext/figure2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/images/onetext/figure2.png
--------------------------------------------------------------------------------
/images/onetext/figure3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/images/onetext/figure3.png
--------------------------------------------------------------------------------
/docs/others/cheatsheets.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/docs/others/cheatsheets.pdf
--------------------------------------------------------------------------------
/docs/others/tutorialbyoscar.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShutterZor/stata-tutorial/HEAD/docs/others/tutorialbyoscar.pdf
--------------------------------------------------------------------------------
/_coverpage.md:
--------------------------------------------------------------------------------
1 | # Awesome Stata Tutorial V1.0
2 |
3 | > 来自 Shutter Zor 的 Stata 入门教程
4 |
5 | [Go!](README.md)
--------------------------------------------------------------------------------
/docs/otherpage.md:
--------------------------------------------------------------------------------
1 | ## Stata Cheatsheets
2 |
3 | [下载链接](https://raw.githubusercontent.com/ShutterZor/stata-tutorial/main/docs/others/cheatsheets.pdf)
4 |
5 | ## Stata Tutorial by Oscar Torres-Reyna
6 |
7 | [下载链接](https://raw.githubusercontent.com/ShutterZor/stata-tutorial/main/docs/others/tutorialbyoscar.pdf)
8 |
--------------------------------------------------------------------------------
/docs/log.md:
--------------------------------------------------------------------------------
1 | # 更新日志
2 |
3 | ## 2023/7/7
4 |
5 | 纠正部分错误
6 |
7 | ## 2023/6/2
8 |
9 | 加入侧边栏 others,增加 Stata 学习资源
10 |
11 | ## 2023/5/19
12 |
13 | 更新图片路径文件
14 |
15 | ## 2023/5/17
16 |
17 | 修正 `oneclick` 网页推文中的部分错误
18 |
19 | ## 2023/5/9
20 |
21 | 修正部分已知错误
22 |
23 | ## 更早的时间
24 |
25 | 忘记具体加了什么内容了,就不写了
--------------------------------------------------------------------------------
/_sidebar.md:
--------------------------------------------------------------------------------
1 | * **Zor's Stata Tutorial**
2 | * [Chapter 1-基本命令](docs/chapter-1.md)
3 | * [Chapter 2-变量处理](docs/chapter-2.md)
4 | * [Chapter 3-数据描述](docs/chapter-3.md)
5 | * [Chapter 4-图形绘制](docs/chapter-4.md)
6 | * **Princeton's Stata Tutorial**
7 | * [Chapter 1-探索你的数据](docs/chapter-5.md)
8 | * **My Program**
9 | * [oneclick](docs/myado/oneclick.md)
10 | * [onetext](docs/myado/onetext.md)
11 | * **Other Resources**
12 | * [Other Resources Link](docs/otherpage.md)
13 | * **Update Date: 2023/7/7**
14 | * [Update Log - 更新日志](docs/log.md)
15 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Stata Tutorial
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.github/workflows/static.yml:
--------------------------------------------------------------------------------
1 | # Simple workflow for deploying static content to GitHub Pages
2 | name: Deploy static content to Pages
3 |
4 | on:
5 | # Runs on pushes targeting the default branch
6 | push:
7 | branches: ["main"]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13 | permissions:
14 | contents: read
15 | pages: write
16 | id-token: write
17 |
18 | # Allow one concurrent deployment
19 | concurrency:
20 | group: "pages"
21 | cancel-in-progress: true
22 |
23 | jobs:
24 | # Single deploy job since we're just deploying
25 | deploy:
26 | environment:
27 | name: github-pages
28 | url: ${{ steps.deployment.outputs.page_url }}
29 | runs-on: ubuntu-latest
30 | steps:
31 | - name: Checkout
32 | uses: actions/checkout@v3
33 | - name: Setup Pages
34 | uses: actions/configure-pages@v3
35 | - name: Upload artifact
36 | uses: actions/upload-pages-artifact@v1
37 | with:
38 | # Upload entire repository
39 | path: '.'
40 | - name: Deploy to GitHub Pages
41 | id: deployment
42 | uses: actions/deploy-pages@v1
43 |
--------------------------------------------------------------------------------
/docs/myado/onetext.md:
--------------------------------------------------------------------------------
1 | # `onetext` 上手指南
2 | ## 0 `onetext` 命令起源
3 | `onetext` 是我自己独立编写的第二条 **Stata** 命令,它主要是对 **Python** 中 `jieba` 库里一些功能的搬运,目的是为了能够在 **Stata** 中直接进行简单的文本分析,避免调用 **Python** ,适当减轻工作负担。但总的来说,目前 `onetext` 的功能还不够完善,在我的设想当中,`onetext` 的终极形态应当是能够完全替代 `jieba` (先画个饼,下次一定)。不过很遗憾,以目前我的能力来看,完全版本的 `onetext` 还很难从技术层面实现。
4 |
5 | 就目前而言,`onetext` 能够统计:
6 |
7 | - 特定词汇是否出现(exist)
8 | - 特定词汇出现的频次(count)
9 | - 计算向量间的余弦相似度(cosine similarity)
10 | - 计算向量间的杰卡德相似度(jaccard similarity)
11 |
12 | ## 1 `onetext` 的 Stata 应用
13 | 首先,该包已成功上传至 **ssc**(The Statistical Software Components)。即,可以通过 **Stata** 中的 `ssc install onetext, replace` 进行下载。在上述命令当中,`ssc install onetext` 代表着从 **ssc** 中下载名为 `onetext` 的命令包,`replace` 选项代表着当 **Stata** 中存在该包时,会下载最新版本的来替代它。
14 |
15 | 具体来看,`onetext` 在 **Stata** 中的应用可以通过以下代码实现(PS:以下代码都已写入 `onetext` 的帮助文件,可以通过 `help onetext` 查看。):
16 |
17 | ```Stata
18 |
19 | *- 从数据当中寻找 “大数据” 三个字出现的次数
20 | clear
21 | set obs 4
22 | gen text = "大数据" in 1
23 | replace text = "大数据大数据" in 2
24 | replace text = "数据小数据" in 3
25 | replace text = "小数据" in 4
26 | onetext text, k("大数据") m(count) g(count_text)
27 |
28 | ```
29 |
30 | 
31 |
32 |
33 | ```Stata
34 |
35 | *- 从数据当中判断 “大数据” 三个字是否出现
36 | clear
37 | set obs 4
38 | gen text = "大数据" in 1
39 | replace text = "大数据大数据" in 2
40 | replace text = "数据小数据" in 3
41 | replace text = "小数据" in 4
42 | onetext text, k("大数据") m(exist) g(isExist)
43 |
44 | ```
45 |
46 | 
47 |
48 |
49 | ```Stata
50 |
51 | *- 计算向量间的相似度
52 | clear
53 | set obs 3
54 | gen var1 = 1 in 1
55 | replace var1 = 2 in 2
56 | replace var1 = 3 in 3
57 | gen var2 = 4 in 1
58 | replace var2 = 2 in 2
59 | replace var2 = 5 in 3
60 | onetext var1 var2, m(cosine) g(cs)
61 | onetext var1 var2, m(jaccard) g(js)
62 |
63 | ```
64 |
65 | 
66 |
67 |
68 | ## 2 结语
69 | 就目前而言, `onetext` 仅仅实现了很小一部分文本分析的功能,希望在未来能够不断地完善它(画饼)。
70 |
71 | 图片加载可能存在问题,点击跳转本推文原始地址以获取更好的阅读体验:[Stata-简单文本分析(onetext命令)](https://mp.weixin.qq.com/s/EoKTpjpxCH5L1iYFwlIy-g)
72 |
73 | 更多应用参考:[Stata:计算文本语调-onetext](https://mp.weixin.qq.com/s/ZGIpFkYfwqTWU9LrZOg8Mw)、[遍历兆字节,约取千人面:OneText文本分析速览](https://mp.weixin.qq.com/s/tD06v9V25c8eqet48I_6cg)
74 |
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## About——致所有阅读到本教程的人
2 |
3 | > 靡不有初,鲜克有终。
4 |
5 | ## About me-关于我
6 |
7 | 左祥太(1999-),男,厦门大学会计学博士研究生。使用 `Stata` 两年多,开发 `Stata` 第三方 ado 文件两份 “`oneclick` 与 `onetext`”,论文发表于*科研管理*、*Journal of Cleaner Production*、*Technology Analysis and Strategic Management* 等。
8 |
9 | - Bilibili:[拿铁一定要加冰](https://space.bilibili.com/40545247)
10 | - 微信公众号:OneStata
11 |
12 | ## About this tutorial-关于本教程
13 |
14 | - **背景:** 从研一,2020 年 12 月开始,截止 2023 年 2 月,我使用 `Stata` 已有两年之余,从中也积累了不少的使用经验。
15 | - **发展:** 从 `连享会` 担任助教后,由于推文工作的原因,收到了不少与 `Stata` 相关的提问邮件,发现很多同学的 `Stata` 基础都较为薄弱,所以我一直想能不能结合我试过的错,编写一本真正意义上的入门级 `Stata` 教程。
16 | - **结果:** 所以自然而然地就编写了这本 `Stata Tutorial` ,并希望有机会阅读到本教程的同学能够从中获取有用的内容。
17 | - **最后:** 本教程所有相关文档、代码整合于本人的 `Stata` 使用经验、普林斯顿大学 `Stata` 教程,以及网络资源。
18 | - 如果在使用过程中遇到无法独立解决的疑惑,或者发现错误内容,请与我联系:Shutter_Z@outlook.com 。
19 |
20 | ## About the technology-关于本站技术
21 |
22 | - **Markdown:** 本教程的 `Markdown` 编辑通过 `Typora` 实现, `Markdown` 转换静态网页资源通过 `docsify` 实现。
23 | - **服务器:** 本站利用 `GitHub Pages` 服务作为远程服务器。
24 | - **域名:** 本站域名经由 `腾讯云` 注册。
25 |
26 | ## About the copyright-关于版权
27 |
28 | **声明:**
29 |
30 | - 阅读网页内容则默认遵守以下开源协议:[Apache License, Version 2.0](LICENSE.md)。
31 | - 使用本网页内容需要标明作者及出处,但作者不对使用本网页后造成的任何不良影响承担责任。
32 | - 版权信息页原始语言为英文,任何由于翻译错误造成对条款的错误解读以及不良后果,由翻译者承担相应责任。
33 |
34 | **版权信息:**
35 |
36 | © Copyright 2022 **Shutter Zor**
37 |
38 | Licensed under the Apache License, Version 2.0 (the "License");
39 | you may not use this file except in compliance with the License.
40 | You may obtain a copy of the License at
41 |
42 | http://www.apache.org/licenses/LICENSE-2.0
43 |
44 | Unless required by applicable law or agreed to in writing, software
45 | distributed under the License is distributed on an "AS IS" BASIS,
46 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
47 | See the License for the specific language governing permissions and
48 | limitations under the License.
49 |
50 | ## About the sponsor-关于赞助
51 |
52 | 欢迎各位大佬通过以下任意途径进行打赏,不论金额多少,都将会于后期列示于下方的资助名单。
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | ## Sponsors list
61 |
62 | 感谢小伙伴的资助,排名不分先后:**K\*F**、**M\*g**、**王\***、**Z\*z**、**匿名用户**、**\*士**、**\*术**、**微信好友**、**\*鱼**、**\*园**、**\*硕**、**\*坤**、**\*静**、**\*桀**、**\*臣**、**\*泽**。
63 |
--------------------------------------------------------------------------------
/docs/chapter-4.md:
--------------------------------------------------------------------------------
1 | ## 4.1 常见图形绘制
2 |
3 | 通过 `help graph` 可以查看 `Stata` 中自带的可视化函数。a
4 |
5 | ```stata
6 | *- 让数据满足绘图要求,二维图形中 (x,y) 需要一一对应
7 | sysuse auto.dta, clear
8 | collapse (mean) price, by(length)
9 |
10 | *- 散点图
11 | twoway scatter price length
12 |
13 | *- 折线图
14 | twoway line price length
15 |
16 | *- 连线图(带样本点的折线图)
17 | twoway connected price length
18 |
19 | *- 柱状图
20 | twoway bar price length // 描述两个变量之间的关系
21 | graph bar price length // 自动取均值后比较
22 |
23 | *- 直方图
24 | histogram price // 面积和为 1
25 |
26 | *- 密度函数图
27 | kdensity price
28 | kdensity price, normal
29 | ```
30 |
31 | ## 4.2 图形选项设置
32 |
33 | ### 4.2.1 常见图形绘制
34 |
35 | 最常见的图形选项设置是分别给 x 轴以及 y 轴加上名称,以及加上图例。
36 |
37 | - 绘制任意函数图像并加上图例与设置角度以及线段颜色、粗细
38 |
39 | ```stata
40 | help twoway function
41 |
42 | twoway (function y=x^2, range(-5 20) lw(*1.5) color(red)) ///
43 | (function y=x^3, range(-5 20) lw(*2.0) color(blue)) ///
44 | (function y=ln(x), range(-5 20) lw(*2.5) color(green)), ///
45 | ylabel(, angle(-45)) ///
46 | yline(0, lcolor(black*0.5) lpattern(dash)) ///
47 | xlabel(, angle(0)) ///
48 | xline(0, lcolor(black*0.5) lpattern(dash)) ///
49 | legend(label(1 "y=x^2") label(2 "y=x^3") label(3 "y=ln(x)")) ///
50 | scheme(s1mono)
51 | ```
52 |
53 | - 绘制 U 型曲线并加上图形标题
54 |
55 | ```stata
56 | sysuse auto.dta, clear
57 |
58 | reg price c.length#c.length
59 |
60 | twoway function y=0.1642153*x^2, range(0 233) ///
61 | ytitle("汽车价格") xtitle("汽车长度") ///
62 | title("价格与长度的二次曲线")
63 |
64 | // 补全负值
65 | twoway (function y=0.1642153*x^2, range(0 233)) ///
66 | (function y=0.1642153*x^2, range(-233 0) lpattern(dash)), ///
67 | ytitle("汽车价格") xtitle("汽车长度") ///
68 | title("价格与长度的二次曲线")
69 | ```
70 |
71 | 此外,关于手动绘制调节效应图形的方法,请参考我的公众号推文[「Stata-手动绘制调节效应图」](https://mp.weixin.qq.com/s/HZ4wZB-0lizPPZKeSeD4ow)。
72 |
73 | ### 4.2.2 图形合并于导出
74 |
75 | ```stata
76 | *- 保存绘制好的图片
77 | sysuse auto.dta, clear
78 | twoway scatter price length
79 | graph save FirstFigure.gph, replace // 保持绘图窗口不关闭时才能保存
80 |
81 | *- 重新调用
82 | graph use FirstFigure.gph
83 |
84 | *- 调用时可换用不同的图片风格
85 | graph use FirstFigure.gph, scheme(s1mono)
86 | graph use FirstFigure.gph, scheme(s2mono)
87 |
88 | *- 推荐使用手动保存方式
89 | sysuse auto.dta, clear
90 | twoway scatter price length
91 |
92 | *- 将图形导出为其他格式
93 | help graph export
94 | sysuse auto.dta, clear
95 | twoway scatter price length
96 |
97 | graph export FirstFigure.png, replace
98 | shellout FirstFigure.png
99 |
100 | // 除 png 格式外,还有 .ps .eps .wmf .emf .pict .tif 等图片格式
101 |
102 | *- 调整输出图片的分辨率
103 | collapse (mean) price, by(length)
104 | twoway connected price length
105 |
106 | graph export SecondFigure.png, width(1280) height(960) replace
107 | shellout SecondFigure.png
108 |
109 | *- 图形的合并(Stata 只能合并 gph 格式图片)
110 | graph combine FirstFigure.gph SecondFigure.gph
111 | graph combine FirstFigure.gph SecondFigure.gph, cols(1)
112 |
113 | *- 删除图形
114 | graph dir
115 | erase FirstFigure.gph
116 | ```
117 |
118 | ### 4.2.3 更改绘图模板
119 |
120 | 使用更优雅的绘图模板请参考我的推文:[「Stata绘图:用 Stata 绘制一打精美图片-schemes」](https://mp.weixin.qq.com/s/NAVd85dXuPNvYJXwIjzd2A)。
121 |
122 | 下载完模板后,放置于相应路径,下次绘图时直接更改图形选项中的 `scheme()` 即可,这里我推荐 `white_tableau`,图形效果见我的其他推文:[Stata-我的一些绘图代码](https://mp.weixin.qq.com/s/VGlhPCb65j8uD8bTRXiOWw)。
123 |
124 | ### 4.2.4 其他有用的图形
125 |
126 | - 事件研究法绘图
127 |
128 | 参考颖宝的推文:[「双重差分法之平行趋势检验」](https://zhuanlan.zhihu.com/p/387732407)。
129 |
130 | - 中国地图绘制
131 |
132 | 参考我的推文:[「Stata:空间计量之用-spmap-绘制地图 」](https://mp.weixin.qq.com/s/aQFtLhzlTjBvGbYXmHagIg)。
133 |
--------------------------------------------------------------------------------
/docs/chapter-3.md:
--------------------------------------------------------------------------------
1 | ## 3.1 虚拟变量分析
2 |
3 | 对于虚拟变量,往往可以采用分组统计的方法来展示它的一些特征。
4 |
5 | ### 3.1.1 分组统计量
6 |
7 | - 一维分组统计量
8 |
9 | ```stata
10 | *- 通过组合 by 与 sum 完成对数据的描述
11 | sysuse auto.dta, clear
12 | by foreign: sum price
13 |
14 | // 等价于
15 | sum price if foreign == 0
16 | sum price if foreign == 1
17 |
18 | *- 通过 tabstat
19 | tabstat price, by(foreign) stat(mean sd med min max)
20 |
21 | *- 通过 tabulate
22 | sysuse auto.dta, clear
23 | tabulate foreign
24 |
25 | sysuse nlsw88.dta, clear
26 | tab occupation
27 | tab occupation, sort
28 | tab occupation, summarize(wage)
29 | ```
30 |
31 | * 二维和三维分组统计量
32 |
33 | ```stata
34 | sysuse nlsw88.dta, clear
35 | bysort race married: sum wage
36 |
37 | bysort race married: tabstat wage, by(union) s(n mean sd p50 min max)
38 |
39 | tabstat wage, by(race married union) s(n mean sd p50 min max) // 错误方式
40 |
41 | bysort race married: tab union, sum(wage)
42 | ```
43 |
44 | - 四维分组统计量
45 |
46 | ```stata
47 | *- 利用 table
48 | sysuse nlsw88.dta, clear
49 | table race married union, by(collgrad) c(mean age) format(%4.2f)
50 |
51 | table union race married, by(collgrad) c(mean wage freq) format(%4.2f)
52 |
53 | // 基本规律
54 | // by() 中的变量与 table 后的第一个变量联合为表的左上角
55 | // 表的第一列为 by() 中的变量分类与 table 后第一个变量的组合
56 | // 表的第一行中从第二列开始为 table 后的第二三个变量的分类组合
57 | ```
58 |
59 | ### 3.1.2 通过其他方式生成分组统计量
60 |
61 | - `egen` 在分组统计时的表现
62 |
63 | ```stata
64 | sysuse nlsw88.dta, clear
65 |
66 | *- 计算不同人种的工资均值
67 | bys race: egen Meanwage = mean(wage)
68 |
69 | *- 计算不同人种的工资中位数
70 | bys race: egen Midwage1 = median(wage)
71 | bys race: egen Midwage2 = pctile(wage), p(50)
72 |
73 | *- 计算不同人种的工资标准差
74 | bys race: egen SDwage = sd(wage)
75 |
76 | preserve
77 | duplicates drop race, force
78 | drop wage
79 | list race *wage*
80 | restore
81 | ```
82 |
83 | - 通过 `collapse` 命令
84 |
85 | 需要注意的是,`collapse` 命令会改变数据框中的数据,使用前需要先备份当前数据。
86 |
87 | ```stata
88 | *- 计算国产车与非国产车价格均值与生产商个数
89 | sysuse auto.dta, clear
90 | collapse (mean) Meanprice=price (count) Nummake=make, by(foreign) // 错误用法,有文字
91 |
92 |
93 | sysuse auto.dta, clear
94 | encode make, gen(Make) // 将文字转为带标签的变量
95 | collapse (mean) price (count) Make, by(foreign)
96 |
97 | *- 自定义生成变量的名称
98 | sysuse auto.dta, clear
99 | encode make, gen(Make)
100 | collapse (mean) Meanprice=price (count) NumMake=Make, by(foreign)
101 |
102 | // 使用后需要重新导入一次数据
103 | // 如仅仅想作图,则可以配合 preserve 与 restore 使用
104 | // preserve 与 restore 可以不改变当前数据
105 | *- 例如
106 | sysuse auto.dta, clear
107 |
108 | preserve
109 | encode make, gen(Make)
110 | collapse (mean) Meanprice=price (count) NumMake=Make, by(foreign)
111 | egen STDprice = std(Meanprice), mean(0) std(1)
112 | egen STDnum = std(NumMake), mean(0) std(1)
113 | twoway (scatter STDprice foreign, color(blue)) ///
114 | (scatter STDnum foreign, color(red))
115 | restore
116 | ```
117 |
118 | ### 3.1.3 图示分组统计量
119 |
120 | - 绘制柱状图
121 |
122 | ```stata
123 | sysuse nlsw88.dta, clear
124 | graph bar (median) wage, over(race) over(married) over(collgrad)
125 |
126 | *- 改变柱状图方向(横向柱状图)
127 | graph hbar (median) wage, over(race) over(married) over(collgrad)
128 | graph hbar (median) wage, over(race) over(married)
129 | graph hbar (median) wage, over(race)
130 | graph hbar (median) wage, over(race) over(married) over(union)
131 | // 最多允许 3 个 over()
132 | ```
133 |
134 | - 增加更多变量
135 |
136 | ```stata
137 | sysuse nlsw88.dta, clear
138 | graph hbar (mean) wage (median) age, over(race) over(married)
139 | graph hbar wage age, over(race) over(married) stack
140 |
141 | *- 改变图中的标签
142 | graph hbar wage age, over(race, relabel(1 "白人" 2 "黑人" 3 "其他")) ///
143 | over(married, relabel(1 "单身" 2 "已婚")) ///
144 | legend(label(1 "工资水平") label(2 "年龄"))
145 | ```
146 |
147 | - 绘制箱型图
148 |
149 | ```stata
150 | sysuse nlsw88.dta, clear
151 |
152 | graph box wage, over(race)
153 | graph box age, over(race) over(married)
154 | graph box age, over(race) over(married) over(union)
155 | graph box age, over(race) over(married) over(union) nooutsides
156 | ```
157 |
158 | ## 3.2 连续变量分析
159 |
160 | ### 3.2.1 描述性统计与结果导出-`sum2docx`
161 |
162 | ```stata
163 | sysuse auto.dta, clear
164 |
165 | rename price 价格
166 | rename headroom 头顶空间
167 | rename length 车长
168 | rename weight 车重
169 |
170 | local Variables 价格 头顶空间 车长 车重
171 | sum2docx `Variables' using 描述性统计表.docx, ///
172 | replace stats(N mean sd median p25 p75 min max) ///
173 | title("描述性统计表1") font("宋体",12,"black") ///
174 | pagesize(A4)
175 |
176 | sum2docx `Variables' using 描述性统计表.docx, ///
177 | replace stats(N mean sd median p25 p75 min max) ///
178 | landscape title("描述性统计表2") font("宋体",12,"black") ///
179 | pagesize(A4)
180 |
181 | // landscape - 设置横向页面
182 | ```
183 |
184 | ### 3.2.2 相关性分析与结果导出-`corr2docx`
185 |
186 | ```stata
187 | sysuse auto.dta, clear
188 |
189 | rename price 价格
190 | rename headroom 头顶空间
191 | rename length 车长
192 | rename weight 车重
193 |
194 | local Variables 价格 头顶空间 车长 车重
195 | corr2docx `Variables' using 相关系数矩阵.docx, ///
196 | replace fmt(%9.3f) title("相关系数矩阵") ///
197 | font("宋体",12,"black") star pagesize(A4) landscape ///
198 | note("注:*** p<0.01, ** p<0.05, * p<0.1")
199 |
200 | // 左下角为 Pearson 相关系数,右上角为 Spearman 相关系数
201 | ```
202 |
--------------------------------------------------------------------------------
/docs/chapter-1.md:
--------------------------------------------------------------------------------
1 | ## 1.1 `Stata` 概述
2 |
3 | > Stata is a complete, integrated software package that provides all your data science needs—data manipulation, visualization, statistics, and automated reporting.
4 | >
5 | > By Statistical software for data science
6 |
7 | ## 1.2 菜单操作
8 |
9 | 需要说明的是,在一般情况下,我们很少通过菜单操作的方式来进行操作,并且长时间不用容易遗忘繁琐的点击步骤,所以不对此进行过多介绍。
10 |
11 | ## 1.3 命令与帮助文件
12 |
13 | ### 1.3.1 基础命令
14 |
15 | 在 `Stata` 中,可以通过在命令窗口输入一行命令后按回车的方式执行命令,也可以将命令写入 `.do` 文件后,运行整个脚本文件或者一行行地运行。请读者自行运行以下命令。
16 |
17 | ```stata
18 | pwd // 显示当前工作路径,与左下角一致
19 | cd E:\Stata16\ado // 进入指定文件夹
20 | sysdir // 查看 Stata 相关路径
21 | ls // 展示当前路径文件,与 linux 类似
22 | dir // 效果同 ls
23 | ```
24 |
25 | ### 1.3.2 认识帮助文件
26 |
27 | `Stata` 的开发者,包括官方开发者与第三方开发者,都会为自己开发的命令文档书写一份帮助文档。在使用过程中如果遇到对命令不熟悉或者其他不清晰的地方,调用帮助文档并自行阅读是最好的学习方法。在 `Stata` 中调用帮助文档的命令为 `help 命令`。比如。
28 |
29 | ```stata
30 | help reg
31 | help regress
32 | ```
33 |
34 | 注意,可以缩写的命令,如 `regress`、`summarize` 等,可以通过 `help 命令缩写` 的方式调用帮助文档。当你不清楚命令是否能缩写时,输入命令的全称是最好的方法。
35 |
36 | ## 1.4 局部宏与全局宏 (`local` & `global`)
37 |
38 | `local` 与 `global` 是 `Stata` 的 `Macro function` 的其中两种常用宏,两者的区别在于。
39 |
40 | - `local` 使用一次便消失,需要同命令一起选中运行
41 | - `global` 可以一直使用,直到关闭 Stata
42 |
43 | ### 1.4.1 `local`
44 |
45 | 需要注意的是,`local` 在引用时左右符号的区别,右边是单引号,而局部宏左边并非单引号,而是英文输入法下 `Esc` 下方的符号。
46 |
47 | - 存放数字并进行运算
48 |
49 | ```stata
50 | local num1 3
51 | dis `num1'
52 |
53 | local num2 `num1' + 5
54 | dis `num2'
55 |
56 | *- 使用双引号时会对展示结果产生影响
57 | local num3 2+2
58 | dis `num3'
59 | dis "`num3'"
60 | ```
61 |
62 | - 存储字符串
63 |
64 | ```stata
65 | local str1 Shutter
66 | dis "`str1'"
67 |
68 | local str2 Zor
69 | dis "`str2'"
70 |
71 | local str3 `str1'`str2'
72 | dis "`str3'"
73 | ```
74 |
75 | - 存储变量,可以增加代码可读性
76 |
77 | ```stata
78 | sysuse auto.dta, clear
79 |
80 | local myVar price mpg rep78
81 | sum `myVar'
82 | *- 等价于
83 | sum price mpg rep78
84 |
85 | local myVar price mpg rep78
86 | pwcorr `myVar'
87 | *- 等价于
88 | pwcorr price mpg rep78
89 |
90 | *- 增加双引号会影响展示结果
91 | local myVar price mpg rep78
92 | dis `myVar'
93 | dis "`myVar'"
94 | ```
95 |
96 | * 简单的数据运算
97 |
98 | ```stata
99 | *- 利用 help mathematical functions 查看Stata支持的所有运算函数
100 | sysuse auto.dta, clear
101 | local num ceil(sqrt(log(100)))
102 | dis `num'
103 | dis make[3]
104 | dis make[`num']
105 | dis make[`=ceil(sqrt(log(100)))']
106 | ```
107 |
108 | * 逻辑运算
109 |
110 | ```stata
111 | sysuse auto.dta, clear
112 | local Yes 1
113 | sum foreign if `Yes'
114 | *- 等价于
115 | sum foreign
116 | ```
117 |
118 | ### 1.4.2 `global`
119 |
120 | 用法基本与 `local` 一致,但引用方式有区别。
121 |
122 | * 存储数字与运算
123 |
124 | ```stata
125 | global num1 5
126 | global num2 $num1 + 10
127 | global str1 Stata代码
128 | global str11 "Stata代码"
129 | global str2 Stata 代码
130 | global str22 "Stata 代码"
131 |
132 | *- 定义时引号可有可无,但引用时对文本信息而言必须加引号,请自行比较
133 | dis $num1
134 | dis $num2
135 | dis "$str1"
136 | dis "$str11"
137 | dis "$str2"
138 | dis "$str22"
139 | dis $str22
140 | ```
141 |
142 | - 常见使用方法
143 |
144 | 定义回归中的控制变量,以简化代码。
145 |
146 | ```stata
147 | sysuse auto.dta, clear
148 | global control mpg headroom weight length turn
149 | reg price $control
150 | ```
151 |
152 |
153 |
154 |
155 |
156 | ## 1.5 条件循环语句及异常处理
157 |
158 | ### 1.5.1 `while` 循环
159 |
160 | 当满足条件时,则执行后续代码。
161 |
162 | ```stata
163 | *- 向上
164 | local boundary 0
165 | while (`boundary'<=3) {
166 | dis _skip(20) `boundary'
167 | local boundary = `boundary' + 1
168 | }
169 |
170 | * 类似于 Python ,上述代码可以简化为
171 | local boundary 0
172 | while (`boundary'<=3) {
173 | dis _skip(20) `boundary++'
174 | }
175 | ```
176 |
177 | ```stata
178 | * 向下
179 | local boundary 0
180 | while (`boundary'>=-3) {
181 | dis _skip(20) `boundary'
182 | local boundary = `boundary' - 1
183 | }
184 |
185 | * 类似于 Python ,上述代码可以简化为
186 | local boundary 0
187 | while (`boundary'>=-3) {
188 | dis _skip(20) `boundary--'
189 | }
190 | ```
191 |
192 | 注意,这些缩进是不必要的,这里只是为了看起来美观。
193 |
194 | ### 1.5.2 `if` 循环
195 |
196 | - `if` 会被很多函数内置
197 |
198 | ```stata
199 | sysuse auto.dta, clear
200 | sum price if foreign == 1
201 | ```
202 |
203 | - 可以与 `else` 连用
204 |
205 | ```stata
206 | local num 11
207 | if (mod(`num',2)==0) {
208 | dis "`num'""是偶数"
209 | }
210 | else {
211 | dis "`num'" "是奇数"
212 | }
213 | ```
214 |
215 | - `if` 与 `else` 套娃使用
216 |
217 | ```stata
218 | local score 90
219 | if (`score'<0)|(`score'>100){
220 | dis "您输入了错误的成绩,请重新输入"
221 | exit
222 | }
223 | if (`score'<=30){
224 | dis "您的成绩为C"
225 | }
226 | if (`score'>30)&(`score'<=60){
227 | dis "您的成绩为B"
228 | }
229 | else {
230 | dis "您的成绩为A"
231 | }
232 | ```
233 |
234 | ### 1.5.3 `forvalues` 循环
235 |
236 | `forvalues` 循环是针对数字部分进行的循环,含有规律数字,则可以使用。
237 |
238 | - 生成 30 个均匀分布的变量 `var1-var30`
239 |
240 | ```stata
241 | clear
242 | set obs 10 // 设定十个观测值,或者说样本
243 | set seed 12345 // 设置随机数种子,以确保结果不是胡乱随机的
244 | forvalues i = 1(1)30 {
245 | gen var`i' = runiform()
246 | }
247 | ```
248 |
249 | ### 1.5.4 `foreach` 循环
250 |
251 | `foreach` 可以对任意非数字的内容进行循环。
252 |
253 | - 批量的对数转换
254 |
255 | ```stata
256 | sysuse auto.dta, clear
257 | local varName price mpg weight length
258 | foreach v in `varName' {
259 | gen ln`v' = ln(`v')
260 | gen log`v' = log(`v')
261 | label var ln`v' "ln(`v') for `v'"
262 | label var log`v' "log(`v') for `v'"
263 | }
264 | list lnprice logprice in 1/10
265 | ```
266 |
267 | 注意,`Stata` 中的 `ln()` 与 `log()` 是等价的,10 为底数,则需要使用 `log10()`,而对于其他的底数,则需要使用[换底公式](https://baike.baidu.com/item/换底公式/6731201)。
268 |
269 | - 批量进行变量缩尾
270 |
271 | ```stata
272 | sysuse auto.dta, clear
273 | local varName price mpg weight length
274 | foreach v in `varName' {
275 | winsor `v', gen(new_`v') p(0.1)
276 | }
277 | histogram price
278 | histogram new_price
279 | ```
280 |
--------------------------------------------------------------------------------
/docs/myado/oneclick.md:
--------------------------------------------------------------------------------
1 | # `oneclick` 5.0 上手指南
2 |
3 | ## 0 `oneclick` 原理
4 |
5 | 我在这里要首先强调 `oneclick` 的原理。它的工作原理仅仅是排列组合控制变量,而不对样本数据造成任何改变,所以它不是万能的,只能在一定程度上帮我们减轻工作量。所以如果你使用了 `oneclick` 却没有得到显著的结果,不要灰心,试一试将变量缩尾、取对数、更换其他的回归方法,以及更换变量的衡量方式。
6 |
7 | 个人认为学术不端跟这个完全不沾边,人工选也是选,机器选也是选,后者效率更高。在机器学习中网格搜索的调参方法与 `oneclick` 是异曲同工的。
8 |
9 | > 人工筛选控制变量并不比机器筛选来得更别具匠心!!!By 知乎用户
10 |
11 | 使用前请先安装更新命令,本版本不再依赖 `tuples`,并且兼容 Stata14.0 及以上版本,执行下列代码即可完成安装:
12 |
13 | ```stata
14 | ssc install oneclick, replace
15 | ```
16 |
17 | ## 1 确定回归方法
18 |
19 | 由于 `oneclick` 使用过程中需要考虑是否添加 `z` 选项,所以在使用 `oneclick` 之前,我们需要先观察回归中用于判定显著性的统计量是否为 `z-value`。若是,则需要添加 `z` 选项,反之则不需要。
20 |
21 | 以 `auto.dta` 数据集为例,假设我们的被解释变量是 *price*,解释变量是 *length*。先用自己需要的回归观测该回归方法下的用于判定显著性的统计量,这里以 `reg` 为例。
22 |
23 | ```stata
24 | *- 调用数据
25 | sysuse auto.dta, clear
26 |
27 | *- 使用回归
28 | reg price length
29 |
30 | *- 返回结果
31 | Source | SS df MS Number of obs = 74
32 | -------------+---------------------------------- F(1, 72) = 16.50
33 | Model | 118425867 1 118425867 Prob > F = 0.0001
34 | Residual | 516639529 72 7175549.01 R-squared = 0.1865
35 | -------------+---------------------------------- Adj R-squared = 0.1752
36 | Total | 635065396 73 8699525.97 Root MSE = 2678.7
37 |
38 | ------------------------------------------------------------------------------
39 | price | Coef. Std. Err. t P>|t| [95% Conf. Interval]
40 | -------------+----------------------------------------------------------------
41 | length | 57.20224 14.08047 4.06 0.000 29.13332 85.27115
42 | _cons | -4584.899 2664.437 -1.72 0.090 -9896.357 726.559
43 | ------------------------------------------------------------------------------
44 | ```
45 |
46 | 根据下方表格,不难发现用于判断显著性的统计量是 `t-value`。
47 |
48 | 以 `auto.dta` 数据集为例,假设我们的被解释变量是 *foreign*,解释变量是 *length*。这个时候使用 `logit` 或者 `probit`,就会发现,用于判定显著性的统计量变为了 `z-value`。
49 |
50 | ```stata
51 | *- logit 回归
52 | logit foreign length
53 |
54 | *- 返回结果
55 | Iteration 0: log likelihood = -45.03321
56 | Iteration 1: log likelihood = -32.059368
57 | Iteration 2: log likelihood = -30.991928
58 | Iteration 3: log likelihood = -30.97462
59 | Iteration 4: log likelihood = -30.974595
60 | Iteration 5: log likelihood = -30.974595
61 |
62 | Logistic regression Number of obs = 74
63 | LR chi2(1) = 28.12
64 | Prob > chi2 = 0.0000
65 | Log likelihood = -30.974595 Pseudo R2 = 0.3122
66 |
67 | ------------------------------------------------------------------------------
68 | foreign | Coef. Std. Err. z P>|z| [95% Conf. Interval]
69 | -------------+----------------------------------------------------------------
70 | length | -.0797353 .0194854 -4.09 0.000 -.117926 -.0415447
71 | _cons | 13.60634 3.457273 3.94 0.000 6.830209 20.38247
72 | ------------------------------------------------------------------------------
73 |
74 | *- probit 回归
75 | probit foreign length
76 |
77 | *- 返回结果
78 | Iteration 0: log likelihood = -45.03321
79 | Iteration 1: log likelihood = -31.110985
80 | Iteration 2: log likelihood = -30.64599
81 | Iteration 3: log likelihood = -30.644666
82 | Iteration 4: log likelihood = -30.644666
83 |
84 | Probit regression Number of obs = 74
85 | LR chi2(1) = 28.78
86 | Prob > chi2 = 0.0000
87 | Log likelihood = -30.644666 Pseudo R2 = 0.3195
88 |
89 | ------------------------------------------------------------------------------
90 | foreign | Coef. Std. Err. z P>|z| [95% Conf. Interval]
91 | -------------+----------------------------------------------------------------
92 | length | -.0474833 .0107435 -4.42 0.000 -.0685403 -.0264264
93 | _cons | 8.099108 1.917156 4.22 0.000 4.341551 11.85667
94 | ------------------------------------------------------------------------------
95 | ```
96 |
97 | 综上,我们通过因变量与自变量之间进行回归的方式,可以确定我们是否需要在 `oneclick` 的选项中加入 `z` 选项。对于常见的回归,我总结一份表格如下。
98 |
99 | | 回归方法 | 是否需要加入 `z` 选项 |
100 | | ------------------------------------- | --------------------- |
101 | | reg | 不需要 |
102 | | logit、ologit、probit、oprobit | 需要 |
103 | | xtreg | 需要 |
104 | | xtreg加re选项构成的随机效应 | 需要 |
105 | | xtreg加fe选项构成的固定效应 | 不需要 |
106 | | 其他任意固定效应模型:reghdfe、areg等 | 不需要 |
107 |
108 | ## 2 保证 `oneclick` 的正确书写
109 |
110 | 首先我们先观察 `oneclick` 的命令构成情况。
111 |
112 | ```stata
113 | *- 基本语法
114 | oneclick y controls, method(regression) pvalue(p-value) fixvar(x and other FE) [
115 | options zvalue ]
116 | ```
117 |
118 | - `y` 位置用来放置你的被解释变量
119 | - `controls` 位置用来放置你的待选控制变量集合,可以是 `i.var` 形式,也可以是 `l.var` 或者 `f.var` 等
120 | - `m()` 位置用来放置你的回归方法,可以是 `reg`、`logit`、`probit`等
121 | - `p()`,在括号中输入你希望的显著性水平,一般是 0.1、0.05,以及0.01。
122 | - `fix()`,在括号中输入你的主要解释变量以及需要每个回归中都出现的变量。比如在一些实证论文中,我们希望能够保留 *size*、*roa* 等其他常见变量,则可以写在解释变量后。**注意:** 第一个位置一定要放解释变量。
123 | - `o()`,用来放置其他原属于回归方法的其他选项,比如 `xtreg y x, re` 中的 `re` 选项、`reghdfe y x, absorb(A B)` 中的 `absorb(A B)` 选项
124 | - `z`,根据第一步中的判定方法考虑是否需要添加以 `z-value` 判别显著性的方法
125 |
126 | ## 3 以正确的姿势开始!
127 |
128 | **我一定一定一定要着重着重着重地强调这一点!!!**
129 |
130 | 我从Bilibili、微信公众号等后台收到的提问内容发现,很多都是大伙儿粗心大意自己写错了,所以我得非常强调一定要自己看清楚代码,所以我这里提到了要用正确的姿势开始对变量的拷打。
131 |
132 | **再三确认回归方法,切忌张冠李戴**
133 |
134 | 在使用 `oneclick` 前,一定要先问自己,自己需要怎样的回归。比如:
135 |
136 | - 是否需要加 `robust` 选项,是的话则需要在 `oneclick` 后面加入 `o(robust)` 。具体而言,如果你的回归形式是 `reg y x, vce(robust)`,则对应的 `oneclick` 代码应该是 `oneclick y 待选控制变量集合, m(reg) fix(x) p(0.1) o(vce(robust))`,而不是`oneclick y 待选控制变量集合, m(reg) fix(x) p(0.1)`。一这样才称得上是一一对应。
137 | - 使用 `xtreg` 时,则需要将你要使用的固定效应 `fe`,或者随机效应 `re`,以及其他选项同时添加到 `o()` 当中。
138 | - 使用 `reghdfe` 时,比如固定个体效应、时间效应的同时需要聚类到行业,可以直接将 `absorb(stkcd year) cluster(industry)` 直接放入 `o()` 中。
139 |
140 | ## 4 查看运算结果
141 |
142 | 在 `oneclick` 运算后,屏幕上会呈现一个简单的运行过程与最后的结论摘要,并且会在当前工作路径下生成一份名为 `subset.dta` 的文件。
143 |
144 | ```stata
145 | *- 调用数据
146 | sysuse auto.dta, clear
147 | (1978 Automobile Data)
148 |
149 | *- 使用 oneclick
150 | oneclick price mpg rep78, fix(weight) p(0.1) m(reg)
151 |
152 | *- 返回结果
153 | This will probably take you up to 1 minutes
154 |
155 | The program is working:
156 | ----+--- 1 ---+--- 2 ---+--- 3 ---+--- 4 ---+--- 5
157 | ...
158 | Time=.027S
159 |
160 | A total of 3 significant groups: 3 positive, 0 negative
161 | ```
162 |
163 | 从结论摘要中,可以发现,一共有3个显著的组合,为什么是3呢?因为我放入了两个待选择的控制变量:*mpg* 与 *rep78*,它们的真子集(非空子集)个数是 2^n-1 = 2^2-1 = 4-1 = 3。所以 `oneclick` 分别将这三种组合带入了运算,并查看了主要解释变量 `weight` 是否在 10% 的显著水平下显著。
164 |
165 | 在这3个显著的组合中,有3种正向显著的情况,都可以使得在 `reg price weight 控制变量` 回归中,*weight* 对 *price* 正向显著。
166 |
167 | 最后,查看当前工作路径下的 `subset.dta` 文件。当前工作路径指的是你当前 Stata 窗口左下角所显示的路径。该文件中有两个变量,一个变量叫 *subset* 用来展示满足显著性要求的控制变量组合,一个变量叫 `positive` 用来展示显著的方向,1表示正向显著,0表示负向显著。
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Copyright information
2 |
3 | **Apache License**
4 | **Version 2.0, January 2004**
5 | http://www.apache.org/licenses/
6 |
7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8 |
9 | **1. Definitions**.
10 |
11 | "**License**" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "**Licensor**" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
14 |
15 | "**Legal Entity**" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "**control**" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
16 |
17 | "**You**" (or "**Your**") shall mean an individual or Legal Entity exercising permissions granted by this License.
18 |
19 | "**Source**" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
20 |
21 | "**Object**" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
22 |
23 | "**Work**" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
24 |
25 | "**Derivative Works**" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
26 |
27 | "**Contribution**" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "**submitted**" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "**Not a Contribution.**"
28 |
29 | "**Contributor**" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
30 |
31 | **2. Grant of Copyright License**. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
32 |
33 | **3. Grant of Patent License**. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
34 |
35 | **4. Redistribution**. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
36 |
37 | 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
38 |
39 | 2. You must cause any modified files to carry prominent notices stating that You changed the files; and
40 |
41 | 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
42 |
43 | 4. If the Work includes a "**NOTICE**" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
44 |
45 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
46 |
47 | **5. Submission of Contributions**. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
48 |
49 | **6. Trademarks**. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
50 |
51 | **7. Disclaimer of Warranty**. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
52 |
53 | **8. Limitation of Liability**. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
54 |
55 | **9. Accepting Warranty or Additional Liability**. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
56 |
57 | END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
/docs/chapter-5.md:
--------------------------------------------------------------------------------
1 | 本节内容翻译自 `Princeton University` 的 `Stata` 教程。当然,我做了适当的修改。原文地址:[DATA & STATISTICAL SERVICES](http://www.princeton.edu/~otorres/Stata/)。
2 |
3 | 当你的 `Stata` 中已经导入数据后,就可以通过如下命令来探索它们:`describe`、`list`、`summarize`,以及 `codebook`。
4 |
5 | ## 1 Describing the data-描述数据
6 |
7 | `describe` 命令将为你提供当前数据集的相关信息(数据集名称等)和变量的格式(“显示格式”)。点击回车键或空格键可以看到其余的列表。输入 `help describe` 以获得更多的细节(如果“--更多--”的信息让你感到困扰,请输入 `set more off`)。
8 |
9 | ```stata
10 | *- 调用自带的数据
11 | sysuse auto.dta
12 |
13 | *- 使用命令
14 | describe
15 |
16 | *- 返回结果
17 | Contains data from E:\Stata16\ado\base/a/auto.dta
18 | obs: 74 1978 Automobile Data
19 | vars: 12 13 Apr 2018 17:45
20 | (_dta has notes)
21 | --------------------------------------------------------------------------------
22 | storage display value
23 | variable name type format label variable label
24 | --------------------------------------------------------------------------------
25 | make str18 %-18s Make and Model
26 | price int %8.0gc Price
27 | mpg int %8.0g Mileage (mpg)
28 | rep78 int %8.0g Repair Record 1978
29 | headroom float %6.1f Headroom (in.)
30 | trunk int %8.0g Trunk space (cu. ft.)
31 | weight int %8.0gc Weight (lbs.)
32 | length int %8.0g Length (in.)
33 | turn int %8.0g Turn Circle (ft.)
34 | displacement int %8.0g Displacement (cu. in.)
35 | gear_ratio float %6.2f Gear Ratio
36 | foreign byte %8.0g origin Car type
37 | --------------------------------------------------------------------------------
38 | Sorted by: foreign
39 | ```
40 |
41 | ## 2 The list command-`list` 命令
42 |
43 | `list` 命令将以表格的形式列出数据,如下所示。
44 |
45 | ```stata
46 | *- 调用自带的数据
47 | sysuse auto.dta
48 |
49 | *- 使用命令
50 | list price mpg in 1/5
51 |
52 | *- 返回结果
53 | +-------------+
54 | | price mpg |
55 | |-------------|
56 | 1. | 4,099 22 |
57 | 2. | 4,749 17 |
58 | 3. | 3,799 22 |
59 | 4. | 4,816 20 |
60 | 5. | 7,827 15 |
61 | +-------------+
62 | ```
63 |
64 | 由于样本总数比较多,这里使用 `in 1/5` 来将显示在屏幕上的数据限制在前 5 个样本,去掉这个限制,即可显示所有样本。
65 |
66 | ## 3 The summarize command-`summarize` 命令
67 |
68 | ### 3.1 描述性统计之 `summarize`
69 |
70 | `summarize` 命令为你提供了更多的数据信息,返回结果将会告诉你样本的数量,它们的平均值、标准差和最小、最大值。注意变量全为 “0”,可能意味着这些变量是文本(或字符串)格式,而不是数字格式。
71 |
72 | ```stata
73 | *- 调用自带的数据
74 | sysuse auto.dta
75 |
76 | *- 使用命令
77 | summarize
78 |
79 | *- 返回结果
80 | Variable | Obs Mean Std. Dev. Min Max
81 | -------------+---------------------------------------------------------
82 | make | 0
83 | price | 74 6165.257 2949.496 3291 15906
84 | mpg | 74 21.2973 5.785503 12 41
85 | rep78 | 69 3.405797 .9899323 1 5
86 | headroom | 74 2.993243 .8459948 1.5 5
87 | -------------+---------------------------------------------------------
88 | trunk | 74 13.75676 4.277404 5 23
89 | weight | 74 3019.459 777.1936 1760 4840
90 | length | 74 187.9324 22.26634 142 233
91 | turn | 74 39.64865 4.399354 31 51
92 | displacement | 74 197.2973 91.83722 79 425
93 | -------------+---------------------------------------------------------
94 | gear_ratio | 74 3.014865 .4562871 2.19 3.89
95 | foreign | 74 .2972973 .4601885 0 1
96 | ```
97 |
98 | 返回结果中变量 `make` 的观测值为 0,点开数据则不难发现,该变量为文本型变量,所有不会参与描述性统计。
99 |
100 | 如果你需要获得某个变量的分位数或者其他统计量,可以在命令之后加上 `,detail`,如下。
101 |
102 | ```stata
103 | *- 调用自带的数据
104 | sysuse auto.dta
105 |
106 | *- 使用命令
107 | summarize price, detail
108 |
109 | *- 返回结果
110 | Price
111 | -------------------------------------------------------------
112 | Percentiles Smallest
113 | 1% 3291 3291
114 | 5% 3748 3299
115 | 10% 3895 3667 Obs 74
116 | 25% 4195 3748 Sum of Wgt. 74
117 |
118 | 50% 5006.5 Mean 6165.257
119 | Largest Std. Dev. 2949.496
120 | 75% 6342 13466
121 | 90% 11385 13594 Variance 8699526
122 | 95% 13466 14500 Skewness 1.653434
123 | 99% 15906 15906 Kurtosis 4.819188
124 | ```
125 |
126 | 此外,对于任意分位数,可以参考 `Chapter 2-变量处理` 中 `2.5 离群值的影响` 中产生分位数的方法。或者直接看如下命令。
127 |
128 | ```stata
129 | *- 通过 summarize 产生分位数
130 | *- 调用自带的数据集
131 | sysuse auto.dta
132 | *- 使用 sum 与 detail 查看详细
133 | sum price, detail
134 | *- 查看命令返回值
135 | return list
136 | *- 将返回值中的 p90 分位数赋值给变量 pctile90
137 | gen pctile90=r(p90)
138 |
139 | *- 通过 _pctile 产生分位数
140 | *- 调用自带的数据集
141 | sysuse auto.dta
142 | *- 使用 _pctile 命令估计变量 price 的 25 和 75 分位数
143 | _pctile price, p(25 75)
144 | *- 查看命令返回值
145 | return list
146 | *- 将返回值中的 p25 与 p75 的分位数赋值给变量 pctile25 与 pctile75
147 | gen pctile25=r(r1)
148 | gen pctile75=r(r2)
149 | *- 利用 sum 检查是否一致
150 | sum price, detail
151 | *- 浏览变量 price 以及它的 25 与 75 分位数
152 | browse price pctile25 pctile75
153 | ```
154 |
155 | ### 3.2 描述性统计之 `tabstat`
156 |
157 | 此外,`tabstat` 命令也可以实现描述性统计的操作,比如。
158 |
159 | ```stata
160 | *- 调用自带的数据
161 | sysuse auto.dta
162 |
163 | *- 使用命令
164 | tabstat price mpg rep78, s(count mean sd min max)
165 |
166 | *- 返回结果
167 | stats | price mpg rep78
168 | ---------+------------------------------
169 | N | 74 74 69
170 | mean | 6165.257 21.2973 3.405797
171 | sd | 2949.496 5.785503 .9899323
172 | min | 3291 12 1
173 | max | 15906 41 5
174 | ----------------------------------------
175 | ```
176 |
177 | 并且,`tabstat` 命令提供的统计量非常之多,通过 `help tabstat`,然后点击 `options👉statistics` 中的 `statname`,可以看到所有支持的统计量。此外,也可以联合 `by()` 选项,完成分组的描述性统计。
178 |
179 | ## 4 Getting a codebook-获得编码手册
180 |
181 | 这个标题可能比较抽象一点,但是如果你看过我前面提到的变量类型,在 `Chapter 2-变量处理` 中 `2.2.1` 小节所提到的,我提到过 `Stata` 中的变量有三种基本的颜色,其中有一种是蓝色,我们可以通过 `codebook` 命令很方便地查看蓝色变量的含义,比如。
182 |
183 | ```stata
184 | *- 调用自带的数据
185 | sysuse auto.dta
186 |
187 | *- 使用命令
188 | codebook foreign
189 |
190 | *- 返回结果
191 | --------------------------------------------------------------------------------
192 | foreign Car type
193 | --------------------------------------------------------------------------------
194 |
195 | type: numeric (byte)
196 | label: origin
197 |
198 | range: [0,1] units: 1
199 | unique values: 2 missing .: 0/74
200 |
201 | tabulation: Freq. Numeric Label
202 | 52 0 Domestic
203 | 22 1 Foreign
204 | ```
205 |
206 | `Stata` 自带的数据中,`foreign` 变量是蓝色的,我们可以通过 `codebook` 命令查看详情,上述结果意味着数字 0 表示国产车,数字 1 表示进口车(国外的车)。
207 |
208 | ## 5. Basic commands-其他基础命令
209 |
210 | ### 5.1 Frequencies (tab)-单变量样本频数
211 |
212 | 接上一个例子,比如我希望进一步了解国产车与进口车的频数,即在我的样本中到底有多少个国产车以及多少个进口车,那么可以使用 `tab` 命令进行查看。
213 |
214 | ```stata
215 | *- 调用自带的数据
216 | sysuse auto.dta
217 |
218 | *- 使用命令
219 | tab foreign
220 |
221 | *- 返回结果
222 | Car type | Freq. Percent Cum.
223 | ------------+-----------------------------------
224 | Domestic | 52 70.27 70.27
225 | Foreign | 22 29.73 100.00
226 | ------------+-----------------------------------
227 | Total | 74 100.00
228 | ```
229 |
230 | 另外,如果你想一次性查看多个变量的单变量频数,可以使用 `tab1` 命令,它会分表依次显示多个变量的具体频数分布。
231 |
232 | ```stata
233 | tab1 make foreign
234 | // 由于结果太长,这里就不展示了
235 | ```
236 |
237 | ### 5.2 Crosstabs (tab)-多变量交叉频数
238 |
239 | 多变量交叉频数指的是观察两个变量之间的频数关系,比如按人种类型(白、黑与其他)统计其婚姻情况,代码如下。
240 |
241 | ```stata
242 | *- 调用自带的数据集
243 | sysuse nlsw88.dta
244 |
245 | *- 使用命令
246 | tab race married
247 |
248 | *- 返回结果
249 | | married
250 | race | single married | Total
251 | -----------+----------------------+----------
252 | white | 487 1,150 | 1,637
253 | black | 309 274 | 583
254 | other | 8 18 | 26
255 | -----------+----------------------+----------
256 | Total | 804 1,442 | 2,246
257 | ```
258 |
259 | 这样我们便可以很方便地观察不同人种之间的婚姻情况数据,比较适用于 `CFPS` 这样式的调查问卷。
260 |
261 | 同时,通过选择 `row` 或者 `column` 选项,可以观察按行或者按列计算的频率,比如。
262 |
263 | ```stata
264 | *- 按行
265 | tab race married, row
266 |
267 | *- 返回结果
268 | +----------------+
269 | | Key |
270 | |----------------|
271 | | frequency |
272 | | row percentage |
273 | +----------------+
274 |
275 | | married
276 | race | single married | Total
277 | -----------+----------------------+----------
278 | white | 487 1,150 | 1,637
279 | | 29.75 70.25 | 100.00
280 | -----------+----------------------+----------
281 | black | 309 274 | 583
282 | | 53.00 47.00 | 100.00
283 | -----------+----------------------+----------
284 | other | 8 18 | 26
285 | | 30.77 69.23 | 100.00
286 | -----------+----------------------+----------
287 | Total | 804 1,442 | 2,246
288 | | 35.80 64.20 | 100.00
289 |
290 | *- 按列
291 | tab race married, column
292 |
293 | *- 返回结果
294 | +-------------------+
295 | | Key |
296 | |-------------------|
297 | | frequency |
298 | | column percentage |
299 | +-------------------+
300 |
301 | | married
302 | race | single married | Total
303 | -----------+----------------------+----------
304 | white | 487 1,150 | 1,637
305 | | 60.57 79.75 | 72.89
306 | -----------+----------------------+----------
307 | black | 309 274 | 583
308 | | 38.43 19.00 | 25.96
309 | -----------+----------------------+----------
310 | other | 8 18 | 26
311 | | 1.00 1.25 | 1.16
312 | -----------+----------------------+----------
313 | Total | 804 1,442 | 2,246
314 | | 100.00 100.00 | 100.00
315 | ```
316 |
317 | 最后,也可以同时加入 `row` 与 `column` 的选项来一次返回按行或者按列计算的多种频率。
318 |
319 | ## 6 T-test T检验
320 |
321 | 主要用于比较两个组别之间的均值差异,比如,比较读大学和不读大学对工资收入的影响。
322 |
323 | ```stata
324 | *- 调用数据
325 | sysuse nlsw88.dta
326 |
327 | *- 使用命令
328 | ttest wage, by(collgrad)
329 |
330 | *- 返回结果
331 | Two-sample t test with equal variances
332 | ------------------------------------------------------------------------------
333 | Group | Obs Mean Std. Err. Std. Dev. [95% Conf. Interval]
334 | ---------+--------------------------------------------------------------------
335 | not coll | 1,714 6.910561 .1276104 5.283132 6.660273 7.16085
336 | college | 532 10.52606 .2742596 6.325833 9.987296 11.06483
337 | ---------+--------------------------------------------------------------------
338 | combined | 2,246 7.766949 .1214451 5.755523 7.528793 8.005105
339 | ---------+--------------------------------------------------------------------
340 | diff | -3.615502 .2753268 -4.155424 -3.07558
341 | ------------------------------------------------------------------------------
342 | diff = mean(not coll) - mean(college) t = -13.1317
343 | Ho: diff = 0 degrees of freedom = 2244
344 |
345 | Ha: diff < 0 Ha: diff != 0 Ha: diff > 0
346 | Pr(T < t) = 0.0000 Pr(|T| > |t|) = 0.0000 Pr(T > t) = 1.0000
347 | ```
348 |
349 | T 检验的的原假设为不存在显著差异,根据 `Ha: diff != 0, Pr(|T| > |t|) = 0.0000`,我们可以判断,显著拒绝原假设,即存在显著差异。所以是否读大学与工资之间的回归应当是显著的,请读者自行验证。
350 |
351 | ## 7 One-way ANOVA-单因素方差分析
352 |
353 | > 该检验的目的是判断每个组的平均数是否相同,即可以视为一种组间差异检验。不同于 T-test 的两组之间的差异比较,One-way ANOVA 可以对多分类的某一个变量构成的不同组别进行均值差异检验。-- By Shutter Zor
354 |
355 | ```stata
356 | *- 调用数据
357 | sysuse nlsw88.dta
358 |
359 | *- 使用命令
360 | oneway wage race
361 |
362 | *- 返回结果
363 | Analysis of Variance
364 | Source SS df MS F Prob > F
365 | ------------------------------------------------------------------------
366 | Between groups 675.510282 2 337.755141 10.28 0.0000
367 | Within groups 73692.4571 2243 32.8544169
368 | ------------------------------------------------------------------------
369 | Total 74367.9674 2245 33.1260434
370 |
371 | Bartlett's test for equal variances: chi2(2) = 21.0482 Prob>chi2 = 0.000
372 | ```
373 |
374 | 结果意味着不同人种之间的工资具有显著的差异(Between groups,Prob>F 为 0.0000),同样地,这使得两者之间的回归结果也变得显著了,请读者自行验证。
--------------------------------------------------------------------------------
/docs/chapter-2.md:
--------------------------------------------------------------------------------
1 | ## 2.1 数据的导入导出
2 |
3 | ### 2.1.1 导入-读入数据
4 |
5 | 常见的数据,这里以 `csv` 格式、`xls`,以及 `xlsx` 为主,介绍利用代码导入的方式。而对于其余格式的数据,可以通过菜单中的 `文件👉导入` 按操作实现。
6 |
7 | - `csv` 格式数据
8 |
9 | ```stata
10 | *- 语法格式
11 | import delimited [using] filename [, import_delimited_options]
12 | *- 实例
13 | import delimited using "E:\data\csvfile.csv", clear
14 | ```
15 |
16 | 一般常用的 `[, import_delimited_options]` 部分只有 `clear` 选项,该选项意味着清除 `Stata` 中的数据,并以新导入的数据覆盖原有的数据框。`注意:` 导入新数据前,务必将已有数据做好备份。
17 |
18 | - `xls` 或者 `xlsx` 格式数据
19 |
20 | ```stata
21 | *- 语法格式
22 | import excel [using] filename [, import_excel_options]
23 | *- 实例
24 | import excel using "E:\data\xlsfile.xls", clear
25 | import excel using "E:\data\xlsxfile.xlsx", clear
26 | ```
27 |
28 | ### 2.1.2 导出-存储数据
29 |
30 | 一般来说我们选择以 `.dta` 格式的文件存储数据。因为后续的一些合并操作都需要先将数据转换为该格式,所以在读入数据并进行简单清洗操作后,我们需要将目前 `Stata` 数据框的文件另存为 `.dta` 文件,代码如下。
31 |
32 | ```stata
33 | *- 语法格式
34 | save [filename] [, save_options]
35 | *- 实例
36 | save data.dta, replace
37 | ```
38 |
39 | 注意 `replace` 选项的使用。第一次存储文件时,不需要使用 `replace`。当发现了该文件有一些错误,需要重新存储为该名字时,则需要加上 `replace` 选项,以替换先前的版本。`注意:` 为了养成良好的数据处理习惯,我建议大家多多备份数据。
40 |
41 | ### 2.1.3 使用 `Stata` 自带的数据
42 |
43 | 在一些特殊的情况下,比如你只想试验一下某条命令,但苦于懒得从其他平台下载数据或者导入数据,那你可以使用 `Stata` 自带的数据来帮你做一些初步的验证。
44 |
45 | ```stata
46 | help dta_examples
47 | ```
48 |
49 | 通过该命令,你可以看到所有 `Stata` 自带的数据集。调用 `Stata` 自带的数据时,需要使用 `sysuse` 而不是 `use`,使用 `use` 则是默认调用 `.dta` 文件。
50 |
51 | ```stata
52 | sysuse auto.dta // 调用 Stata 自带的 auto 数据集
53 | use auto.dta // 调用当前路径下的 auto.dta 文件
54 | ```
55 |
56 | ## 2.2 变量生成
57 |
58 | 当导入数据后,在存储数据之前,我们一般会通过一些变量生成操作,或者说数据转换操作,来对导入的数据进行一些初步的处理。
59 |
60 | ### 2.2.1 `Stata` 中变量的三种颜色
61 |
62 | 你可能已经注意到,在 `Stata` 的数据框中,可能会存在三种颜色的数据。如果你一直维持默认的配色,那这三种颜色会是黑色、红色以及蓝色,它们分别对应不同类型的变量。
63 |
64 | - 黑色:数值型变量,可以直接加减乘除
65 | - 红色:文本型变量,可以进行文本字符运算
66 | - 蓝色:数值-文本交叉型变量,以文本方式显示,但本质是数值型,可以直接运算
67 |
68 | ### 2.2.2 `_n` 与 `_N`
69 |
70 | `_n` 与 `_N` 是 `Stata` 中较为特殊的存在,巧用它俩,能很好地帮助我们解决一些实际问题。
71 |
72 | - `_n` 可以理解为样本的序列编号(1,2,...,n)
73 | - `_N` 可以理解为样本序列编号的最大值(n)
74 |
75 | 请读者自行根据下列代码验证区别,获得更直观的理解。
76 |
77 | ```stata
78 | * _n 与 _N 的区别
79 | sysuse auto.dta, clear
80 | gen var1 = _n
81 | gen var2 = _N
82 | list price var1 var2 in 1/5
83 |
84 | sort price
85 | gen var3 = _n
86 | list var1 var3 in 1/5 // _n 随排序而发生变化
87 |
88 | dis _n
89 | dis _N
90 |
91 | sum price
92 | dis r(N)
93 | dis _N
94 | ```
95 |
96 | 在实际应用当中,我列举几个常用的例子,具体如下。
97 |
98 | - 将截面数据转换为平衡面板
99 |
100 | ```stata
101 | // TextileCode 仅包括一个变量 code,具体内容为纺织行业上市公司代码
102 | // 因为作者本人本硕均就读于武汉纺织大学
103 | // 并且发表于 Journal of Cleaner Production 的论文就是纺织业数据
104 | // 所以这里用了纺织业的上市公司代码,但这里可以替换成任意不重复的某个行业的上市公司代码
105 | // 除上市公司外,该方法适用于生成任何平衡面板数据
106 |
107 | import excel using TextileCode.xls, first clear
108 | expand 10
109 | sort code
110 |
111 | by code: gen temp = _n
112 | by code: gen year = 2009 + temp
113 |
114 | // 等价于
115 | import excel using TextileCode.xls, first clear
116 | expand 10
117 | bys code: gen year = 2009 + _n
118 | ```
119 |
120 | - 差分计算
121 |
122 | ```stata
123 | sysuse sp500.dta, clear // Stata 自带的数据
124 | gen Dclose1 = close[_n] - close[_n-1]
125 |
126 | tsset date
127 | gen Dclose2 = D.close
128 |
129 | list Dclose1 Dclose2 in 1/10 // 日期不连续问题
130 |
131 | // 此处差异在处理时间序列数据时需要着重考虑
132 | ```
133 |
134 | - 滞后项或提前项
135 |
136 | ```stata
137 | sysuse sp500.dta, clear
138 | tsset date
139 |
140 | *- 生成滞后项
141 | gen Lclose1 = close[_n-1]
142 | gen Lclose2 = L.close
143 | list Lclose* in 1/10
144 |
145 | gen L2close1 = close[_n-2]
146 | gen L2close2 = L2.close
147 | list L2close* in 1/10
148 |
149 | *- 生成提前项
150 | gen Fclose1 = close[_n+1]
151 | gen Fclose2 = F.close
152 | list Fclose* in 1/10
153 | ```
154 |
155 | `注意:` 对于时间序列数据而言,尤其是股价这种非连续时间的数据,尽量通过 `Stata` 的 `L.`、`D.`,以及 `F.` 等来分别生成滞后、差分、提前项,而避免手动生成所导致的偏差。
156 |
157 | - 计算增长率
158 |
159 | ```stata
160 | sysuse sp500.dta, clear
161 | tsset date
162 |
163 | gen Ratio1 = (close[_n]-close[_n-1])/close[_n-1]
164 | gen Ratio2 = D.close/L.close
165 | gen lnclose = ln(close)
166 | gen Ratio3 = D.lnclose
167 |
168 | list Ratio* in 1/10
169 | ```
170 |
171 | 注意,`Ratio1` 与 `Ratio2` 等价,即对数差分能替代增长率,这可能是一个[等价无穷小](https://baike.baidu.com/item/等价无穷小/7796020)的关系。也可以参考如下回答:[计量经济学中为什么要对变量取对数,差分以及对数差分?](https://www.zhihu.com/question/31722222)。
172 |
173 | - 计算移动平均
174 |
175 | ```stata
176 | * 常规做法
177 | sysuse sp500.dta, clear
178 | tsset date
179 | keep date close
180 |
181 | gen L1close = L.close
182 | gen L2close = L2.close
183 | gen L3close = L3.close
184 |
185 | egen MA3close = rowmean(L1close-L3close)
186 | gen MA3close1 = F.MA3close
187 | replace MA3close1 = . if mod(_n,3) != 0 // 仅保留第三期
188 |
189 | * 利用 _n 简化(可能有问题)
190 | gen MA3close2 = (close[_n-1] + close[_n] + close[_n+1]) / 3
191 | gen MA3close3 = MA3close2[_n-1]
192 | replace MA3close3 = . if mod(_n,3) != 0
193 |
194 | list close L* MA3* in 1/10
195 | dis (1333.34+1347.56+1283.27)/3
196 | dis (1283.27+1347.56+1333.34)/3
197 |
198 | * 看看两种做法的差异
199 | ttest MA3close1 = MA3close3
200 | ```
201 |
202 | ### 2.2.3 虚拟变量
203 |
204 | `虚拟变量` 指的是分类变量,用数字来代替一些不同的类别,它们之间并不构成严格的大小关系。例如:男性取 1, 女性取 0,男女平等,所以在这种情况下 1>0 是显然不成立的。
205 |
206 | - 使用 `generate` 与 `replace` 生成虚拟变量,注意 `generate` 可以简写为 `gen`
207 |
208 | ```stata
209 | sysuse auto.dta, clear
210 |
211 | * 依据 headroom 划分汽车舒适度(不够严谨)
212 | // 对连续变量生成
213 | sum headroom, detail
214 | return list
215 |
216 | gen Comfort = 1 if headroom >= r(p50)
217 | replace Comfort = 0 if headroom < r(p50)
218 |
219 | * 根据 foreign 生成国产变量
220 | // 对虚拟变量生成虚拟变量
221 | gen Domestic = 1 if foreign == 0
222 | replace Domestic = 0 if foreign == 1
223 |
224 | * 给这些虚拟变量打上标签,由黑变蓝
225 | // 展示数据有用,但合并时会造成混乱(不推荐)
226 | label define Comfort_label 1 "舒适" 0 "不舒适"
227 | label define Domestic_label 1 "国产" 0 "非国产"
228 | label values Comfort Comfort_label
229 | label values Domestic Domestic_label
230 | ```
231 |
232 | - 利用 `tab` 生成虚拟变量
233 |
234 | ```stata
235 | *- 将上述代码简化为
236 | sysuse auto.dta, clear
237 | tab foreign, gen(Dummy)
238 | ```
239 |
240 | 注意,这是一种[独热编码(one-hot)](https://baike.baidu.com/item/独热编码?fromModule=lemma_search-box),生成的变量是完全共线的。`注意:` `tab` 与后面介绍的 `tabstat` 是不同的命令。
241 |
242 | - 将样本等分并产生虚拟变量
243 |
244 | ```stata
245 | sysuse auto.dta, clear
246 | sort price
247 | gen Group = group(4)
248 | browse price Group
249 | tabstat price, stat(N) by(Group) f(%4.2f)
250 |
251 | // 按照分位数分组也可达到相似效果
252 | sum price, detail
253 | return list // 查看函数运行完之后的返回值
254 | gen Group1 = 1 if price <= r(p25)
255 | replace Group1 = 2 if (price>r(p25)) & (price<=r(p50))
256 | replace Group1 = 3 if (price>r(p50)) & (price<=r(p75))
257 | replace Group1 = 4 if price>r(p75)
258 | tabstat price, stat(N) by(Group1) f(%4.2f)
259 | ```
260 |
261 | - 按任意分位点产生虚拟变量
262 |
263 | ```stata
264 | sysuse auto.dta, clear
265 | _pctile price, p(1 3 6 10 34 91)
266 | return list
267 | ```
268 |
269 | 上述代码是生成 1、3、6、10、34、91 等分位数的值,利用 `gen` 、`replace` 以及内置的 `if` 即可任意生成虚拟变量。
270 |
271 | - 对文本生成虚拟变量
272 |
273 | ```stata
274 | *- 这是一份包含大陆地区 34 个主要省市区名称的 dta 文件
275 | use MainlandChina.dta, clear
276 | gen Middle = inlist(province,"山西","河南","安徽","湖北","江西","湖南")
277 | ```
278 |
279 | 在这个例子中,我使用了 `inlist`,它的含义是,对于变量 `province` 如果里面出现了后面这些文本值,则取 1,反之取 0。
280 |
281 | ### 2.2.4 神奇的 `egen`
282 |
283 | `egen` 的全称是 `extensions to generate`,不难看出,它是对 `generate` 的扩充,用于实现一些神奇的功能,可以通过 `help egen` 查看 `egen` 支持的所有运算函数,这里只介绍几个常用的。
284 |
285 | - `egen` 与 `gen` 的求和差异
286 |
287 | ```stata
288 | sysuse auto.dta, clear
289 | gen sumprice1 = sum(price) // 累加
290 | egen sumprice2 = sum(price) // 总和
291 | list price sumprice* in 1/10
292 | list price sumprice* in -1
293 | ```
294 |
295 | - `egen` 与 `gen` 生成均值时的差异
296 |
297 | ```stata
298 | *- 生成数据
299 | clear
300 | set obs 10
301 | set seed 12345
302 | gen x1 = 10*runiform()
303 | gen x2 = 10*runiform()
304 |
305 | *- 随机缺失值,随机生成一些缺失值
306 | foreach v in x1 x2 {
307 | replace `v' =. if mod(ceil(`v'),2) == 0
308 | }
309 | list x*
310 |
311 | *- 生成均值比较差异
312 | gen mean1 = (x1+x2)/2
313 | egen mean2 = rowmean(x1 x2)
314 | list x* mean*
315 | ```
316 |
317 | - 生成等差数列
318 |
319 | ```stata
320 | *- 手动生成等差数列方式(初始项为1,公差为2)
321 | clear
322 | set obs 100
323 | set seed 12345
324 | gen X = 1 in 1
325 | forvalues i = 2/100{
326 | replace X = 1 + (`i' - 1) * 2 in `i'
327 | }
328 |
329 | *- 尝试仿照上述方法编写等比数列计算代码
330 | gen Y = 1 in 1
331 | forvalues i = 2/100{
332 | replace Y = 1 * 2^((`i' - 1)) in `i'
333 | }
334 |
335 | *- 利用 egen 简化
336 | egen Z1 = seq(), from(1)
337 | egen Z2 = seq(), from(1) to(199) // seq() 无法改变公差
338 |
339 | egen A1 = fill(1 3) // 可以制造任意等差
340 | egen A2 = fill(3 1)
341 | ```
342 |
343 | - `egen` 中最常见的指标计算
344 |
345 | ```stata
346 | *- 生成均值、中位数、标准差、最小值、最大值(纵向,按变量)
347 | sysuse auto.dta, clear
348 | egen Average = mean(price), by(foreign)
349 | egen Median = median(price), by(foreign)
350 | egen StdDev = sd(price), by(foreign)
351 | egen Min = min(price), by(foreign)
352 | egen Max = max(price), by(foreign)
353 | browse
354 |
355 | *- 横向对比,按样本
356 | egen Difference = diff(Min Max)
357 | egen Mean = rowmean(Min Max)
358 | ```
359 |
360 | * 利用 `egen` 简化变量标准化步骤
361 |
362 | ```stata
363 | *- 手动标准化
364 | sysuse auto.dta, clear
365 | sum price
366 | gen STDprice1 = (price - r(mean))/r(sd)
367 | sum STDprice1
368 | list *price in 1/10
369 |
370 | *- 通过 egen 简化实现步骤
371 | egen STDprice2 = std(price), mean(0) std(1)
372 | sum STDprice*
373 | list *price in 1/10
374 | ```
375 |
376 | * 利用 `egen` 计算移动平均
377 |
378 | ```stata
379 | sysuse sp500.dta, clear
380 | tsset date
381 | egen MA1 = ma(close) // 默认 3 期
382 | egen MA2 = ma(close), t(3)
383 | egen MA3 = ma(close), t(3) nomiss
384 | list close MA* in 1/10
385 |
386 | dis (1283.27+1347.56)/2 // 第一个值
387 | dis (1283.27+1347.56+1333.34)/3 // 第二个值
388 | dis (1347.56+1333.34+1298.35)/3 // 第三个值
389 | // 在加入nomiss的时候,不会存在缺失值,取而代之的是 n-1 期均值
390 | ```
391 |
392 | ## 2.3 重复样本处理
393 |
394 | ### 2.3.1 观测是否存在重复样本
395 |
396 | - 通过 `isid` 识别
397 |
398 | ```stata
399 | sysuse auto.dta, clear
400 | isid make
401 | isid foreign
402 | ```
403 |
404 | - 通过 `duplicates` 识别
405 |
406 | ```stata
407 | sysuse auto.dta, clear
408 | duplicates list foreign
409 | duplicates report foreign
410 | duplicates example foreign
411 | ```
412 |
413 | ### 2.3.2 删除重复样本
414 |
415 | 首先需要确认删除什么样的重复样本,以最常用的上市公司面板数据而言,对于每个公司,其每年的数据应当是唯一的,所以应当以上市公司代码 `stkcd` 以及年份变量 `year` 为准,删除重复值,代码如下。
416 |
417 | ```stata
418 | duplicates drop stkcd year, force
419 | ```
420 |
421 | ## 2.4 缺失值处理
422 |
423 | ### 2.4.1 认识不同的缺失值
424 |
425 | 在 `Stata` 中,有一些不同的缺失值表示方式,最常见的就是以 `.` 来表示变量中的缺失。通过 `help missing`,我们可以得到如下一段描述。
426 |
427 | ```stata
428 | Stata has 27 numeric missing values:
429 | ., the default, which is called the "system missing value" or sysmiss
430 | and
431 | .a, .b, .c, ..., .z, which are called the "extended missing values".
432 | Numeric missing values are represented by large positive values. The ordering is
433 | all nonmissing numbers < . < .a < .b < ... < .z
434 | Thus, the expression age > 60 is true if variable age is greater than 60 or
435 | missing.
436 | To exclude missing values, ask whether the value is less than ".". For instance,
437 | . list if age > 60 & age < .
438 | To specify missing values, ask whether the value is greater than or equal to ".".
439 | For instance,
440 | . list if age >=.
441 | Stata has one string missing value, which is denoted by "" (blank).
442 | ```
443 |
444 | 这段话的大致意思就是 `Stata` 一共有 27 种数值型变量的缺失值,以及 1 种文本型变量的缺失值。在数值型缺失值中,`.` 是默认的,对于 `.` + 26 个小写英文字母所构成的扩展缺失值,依次有一个大小关,所以如果我们在处理一些类似于个体调查问卷的时候,如果需要保留大于 60 岁的样本,则需要让年龄变量 `age` 同时小于缺失值 `.`,不然缺失值不会被剔除,并且缺失值大于所有的自然数。
445 |
446 | ### 2.4.2 判断缺失值的存在性
447 |
448 | `注意:` 这里需要先区分一个概念,样本与变量,在 `Stata` 中,横向的一般为样本,纵向的为变量。
449 |
450 | - 查找变量中是否有缺失值(纵向)。确定一个变量中是否存在缺失值,最好的方式就是观测该变量中的数值个数是否与样本总数一致,具体代码如下。
451 |
452 | ```stata
453 | sysuse auto.dta, clear
454 | sum price rep78
455 | dis _N
456 | ```
457 |
458 | 如果描述性统计之后,`price` 的观测值为 74,`rep78` 的观测值个数为 69,样本总数为 74,所以 `rep78` 存在 5 个缺失值。同样地,也可以通过 `misstable` 命令更好地观察缺失值。
459 |
460 | ```stata
461 | sysuse auto.dta, clear
462 | misstable summarize // 对所有变量
463 | misstable sum price-length // 对指定变量
464 | // 该命令仅报告存在缺失的变量(不计算文本变量)
465 | ```
466 |
467 | - 查找样本中是否存在缺失值(横向)。确定一个样本是否存在缺失变量。
468 |
469 | ```stata
470 | sysuse auto.dta, clear
471 | egen Rowmiss = rowmiss(price rep78 weight length)
472 | list price rep78 weight length if Rowmiss == 1
473 | ```
474 |
475 | 在样本中,但凡有一个变量是缺失值,就默认该样本为缺失,并且缺失样本不参与后续回归。
476 |
477 | ### 2.4.3 处理缺失值
478 |
479 | 注意我的做法,这里与其他 `Stata` 教程直接教你均值填充不同,我会教你优先判断缺失的比例。
480 |
481 | - 判断缺失值的比例
482 |
483 | 首先,我们可以通过一串建议的代码判断某一个缺失值的比例,比如。
484 |
485 | ```stata
486 | sysuse auto.dta, clear
487 | sum
488 | dis "rep78变量缺失值比例=" (_N-69)/_N*100
489 | ```
490 |
491 | 这个 69 是我们运行描述性统计后,变量 `rep78` 中的观测值个数,我们用样本总数减去变量的观测值数再除以样本总数并乘以 100,就能够得到改变量的缺失比例。
492 |
493 | 接下来,我们结合之前所学习到的局部宏与 `foreach` 循环,可以批量展示变量的缺失比例,具体代码如下。
494 |
495 | ```stata
496 | sysuse auto.dta, clear
497 | local Variables price mpg rep78 headroom trunk weight length
498 | foreach v in `Variables' {
499 | quietly summarize `v'
500 | dis _skip(10) "`v'的缺失比例为=" (_N-r(N))/_N*100
501 | }
502 | ```
503 |
504 | - 对连续变量可采用均值填补策略
505 |
506 | 如果在上面的缺失比例判断中,比例并不是很大,个人认为缺失比例小于 30% 的情况下可以直接填充,均值填充适用于连续型变量,填充代码如下。
507 |
508 | ```stata
509 | *- 填充单个变量
510 | sysuse auto.dta, clear
511 | egen rep78mean = mean(rep78)
512 | replace rep78 = rep78mean if rep78 == .
513 | drop rep78mean
514 |
515 | *- 批量填充
516 | local Variables price mpg rep78
517 | foreach v in `Variables' {
518 | egen `v'mean = mean(`v')
519 | replace `v' = `v'mean if `v' == .
520 | drop `v'mean
521 | }
522 | ```
523 |
524 | - 对分类变量或者说虚拟变量,可以通过众数填充
525 |
526 | ```stata
527 | sysuse auto.dta, clear
528 | replace foreign = . in 3
529 | replace foreign = . in 70
530 | tab foreign // 查看不同类别的频次
531 | labelbook // 查看不同类别对应的数值
532 | replace foreign = 0 if foreign == .
533 | ```
534 |
535 | - 向前/向后填充,利用前面或者后面的值进行邻接填充
536 |
537 | ```stata
538 | *- 向后填充(上一期替代本期缺失)
539 | replace X = X[_n-1] if X == .
540 | replace Y = Y[_n-1] if Y == ""
541 |
542 | *- 向前填充(下一期替代本期缺失)
543 | replace X = X[_n+1] if X == .
544 | replace Y = Y[_n+1] if Y == ""
545 |
546 | *- 对面板数据而言,最好使用 L 与 F
547 | xtset Num Year
548 | bys Num: replace Random = L.Random if mi(Random)
549 | bys Num: replace Random = F.Random if mi(Random)
550 | ```
551 |
552 | 需要注意的是,对于非连续时间样本,这里的时间指的是你 `xtset Num Year` 中的时间,如果不连续,比如样本时间跨度是 2010-2021,而一家公司的数据是 2010、2011、2015、2021,中间存在一些间隔时间,在这种情况下使用 `L.` 与 `F.` 是正确的,而使用 `[_n-1]` 或者 `[_n+1]` 将会使得数据被过度填充。
553 |
554 | ## 2.5 离群值处理
555 |
556 | ### 2.5.1 什么是离群值
557 |
558 | 离群值是脱离数据群体的值,极大极小值不一定为离群值。数据群体指的是处于 (p25-1.5iqr, p75+1.5iqr) 之间的值。四分位间距(interquartile range):iqr = p75 - p25,p25、p75 分别指处于第 1 个四分位(第 25 个百分位),p25、p50、p75 分别叫第 1、2、3 个四分位,p50 即中位数。
559 |
560 | ### 2.5.2 离群值的影响
561 |
562 | 在下面的例子中,我构造了一个叫 `tempvar` 的变量来识别该样本的 `price`变量是否为离群值,然后分别以纳入该样本与不纳入该样本的方式进行两次回归,并比较两次回归的结果。
563 |
564 | ```stata
565 | sysuse auto.dta, clear
566 | _pctile price, p(25 75)
567 | dis "p25=" r(r1)
568 | dis "p75=" r(r2)
569 |
570 | local Lower r(r1)-1.5*(r(r2)-r(r1))
571 | local Upper r(r2)+1.5*(r(r2)-r(r1))
572 |
573 | gen tempVar = 1 if price>`Upper' | price<`Lower'
574 | sum tempVar
575 |
576 | reg price mpg rep78
577 | est store Model1
578 | reg price mpg rep78 if tempVar != 1
579 | est store Model2
580 | esttab Model1 Model2, nogap compress mtitle("Yes" "No")
581 |
582 | reg mpg rep78 price
583 | est store Model1
584 | reg mpg rep78 price if tempVar != 1
585 | est store Model2
586 | esttab Model1 Model2, nogap compress mtitle("Yes" "No")
587 | ```
588 |
589 | 最后在 `Stata` 界面,我们可以发现,离群值的存在会改变模型的解释。
590 |
591 | ### 2.5.3 查找离群值
592 |
593 | - 手动编写一条查找离群值的命令
594 |
595 | ```stata
596 | sysuse auto.dta, clear
597 |
598 | local Variables price mpg rep78 headroom trunk
599 | foreach v in `Variables' {
600 | _pctile `v', p(25 75)
601 | scalar Lower = r(r1)-1.5*(r(r2)-r(r1))
602 | scalar Upper = r(r2)+1.5*(r(r2)-r(r1))
603 | quietly sum `v'
604 | if (r(max)>Upper) | (r(min)Upper | `v' 8814 | price < 3291
630 | sum tempVar
631 | ```
632 |
633 | ### 2.5.4 处理离群值
634 |
635 | 处理离群值的方法有很多,常见的有截尾处理、缩尾处理以及对数转换。
636 |
637 | - 截尾处理,截尾是指将尾巴处样本直接删除或者转为缺漏值
638 |
639 | ```stata
640 | *- 通过adjacent
641 | sysuse auto.dta, clear
642 | adjacent price
643 | drop if price > 8814 | price < 3291
644 |
645 | *- 通过 _pctile
646 | sysuse auto.dta, clear
647 | _pctile price, p(25 75)
648 |
649 | local Lower r(r1)-1.5*(r(r2)-r(r1))
650 | local Upper r(r2)+1.5*(r(r2)-r(r1))
651 | drop if price > `Upper' | price < `Lower'
652 | ```
653 |
654 | - 缩尾处理,缩尾是指将尾巴末端处转为最后一个非极端值
655 |
656 | ```stata
657 | sysuse auto.dta, clear
658 |
659 | *- 判断是否需要缩尾的利器,直方图
660 | histogram price
661 |
662 | *- 双边缩尾,对变量极大极小值同时缩尾
663 | winsor price, gen(price_W) p(0.05)
664 |
665 | twoway (histogram price, color(red)) (histogram price_W, color(blue)),legend(label(1 "原始数据") label(2 "缩尾后"))
666 |
667 | *- 仅对右侧缩尾
668 | graph box price // 目测仅需对右侧缩尾
669 |
670 | dis 12/74
671 | winsor price, gen(price_HW) p(0.15) highonly
672 | graph box price_HW
673 |
674 | *- 如果仅对左侧缩尾,则选择 lowonly 选项替换 highonly
675 | twoway (histogram price, color(red)) (histogram price_HW, color(blue)), legend(label(1 "原始数据") label(2 "右侧缩尾后"))
676 |
677 | *- 通过 _pctile 任意点位缩尾
678 | sysuse auto.dta, clear
679 |
680 | _pctile price, p(6 94)
681 | gen price_ = price
682 | replace price_ = r(r1) if price_ < r(r1)
683 | replace price_ = r(r2) if price_ > r(r2)
684 |
685 | twoway (histogram price, color(red)) (histogram price_, color(blue)), legend(label(1 "原始数据") label(2 "任意缩尾后"))
686 | ```
687 |
688 | - 对数转换,使数据分布更加合理
689 |
690 | ```stata
691 | sysuse auto.dta, clear
692 | expand 2
693 | gen temp = 1 in 1/74
694 | replace temp = 0 if temp == .
695 | gen lnprice = ln(price) if temp == 0
696 | replace lnprice = price if temp == 1
697 | replace lnprice = lnprice/1000 if temp == 1
698 |
699 | graph box lnprice, by(temp)
700 | ```
701 |
702 | ## 2.6 数据的合并与追加
703 |
704 | - 横向合并,即增加变量,相当于 `Excel` 的 `VLOOKUP`
705 |
706 | ```stata
707 | *- 一对一合并(1:1)
708 | *- Data1
709 | * make var1
710 | * AA 2
711 | * BB 3
712 |
713 | *- Data2
714 | * make var2
715 | * AA 5
716 | * BB 6
717 |
718 | *- 观察 Data1 与 Data2 可知,两份数据中 make 都是唯一对应一条样本的,所以以 make 为关键词
719 | use Data1.dta, clear
720 | merge 1:1 make using Data2.dta
721 |
722 | *- 合并后
723 | * make var1 var2
724 | * AA 2 5
725 | * BB 3 6
726 |
727 | // 注意,该方法可应用于面板对面板的合并,比如以 stkcd 以及 year 为关键词分别对应唯一的样本
728 |
729 | *- 此时会新生成一个 _merge 变量,含义如下:
730 | *- _merge==1 observation appeared in master only
731 | *- _merge==2 observation appeared in using only
732 | *- _merge==3 observation appeared in both
733 |
734 | * 多对一合并(m:1)
735 | *- 多见于面板数据,把财务面板数据与企业基本信息合并等
736 | *- Data3 为企业的面板数据,数据大致如下
737 | * stkcd year
738 | * 1 2001
739 | * 1 2002
740 | * 2 2001
741 | * 2 2002
742 |
743 | *- Data4 为企业的基本信息,数据大致如下
744 | * stkcd province
745 | * 1 湖北
746 | * 2 湖南
747 |
748 | *- Data3 中一个企业代码对应多个样本,Data4 中一个企业代码对应一条数据,所以是 m:1
749 | use Data3.dta, clear
750 | merge m:1 stkcd using Data4.dta
751 |
752 | *- 合并后
753 | * stkcd year province
754 | * 1 2001 湖北
755 | * 1 2002 湖北
756 | * 2 2001 湖南
757 | * 2 2002 湖南
758 |
759 | * 一对多合并(1:m)逆过程
760 | use Data4.dta, clear
761 | merge 1:m Num using Data3.dta
762 |
763 | *- 注意合并时一定要保证主表与被合并表的关键词名称相同
764 | ```
765 |
766 | - 纵向合并,增加样本值,相当于在 `Excel` 后面追加数据
767 |
768 | ```stata
769 | *- Data1
770 | * make var1
771 | * AA 2
772 | * BB 3
773 |
774 | *- Data2
775 | * make var2
776 | * AA 5
777 | * BB 6
778 |
779 | use Data1.dta, clear
780 | append using Data2.dta
781 |
782 | *- 追加后
783 | * make var1 var2
784 | * AA 2 .
785 | * BB 3 .
786 | * AA . 5
787 | * BB . 6
788 | ```
789 |
790 | ## 2.7 长宽数据转换
791 |
792 | ```stata
793 | *- 宽数据转长数据
794 | *- 生成数据
795 | clear
796 | input id sex inc80 inc81 inc82 xx80 xx81 xx82
797 | 1 0 5000 5500 6000 1 2 3
798 | 2 1 2000 2200 3300 2 3 4
799 | 3 0 3000 2000 1000 6 4 8
800 | end
801 |
802 | *- 转换数据
803 | reshape long inc xx, i(id) j(year)
804 |
805 | *- 长数据转宽数据
806 | *- 生成数据
807 | clear
808 | input id year sex inc xx
809 | 1 1880 0 5000 1
810 | 1 1881 0 5500 2
811 | 1 1882 0 6000 3
812 | 2 1880 1 2000 2
813 | 2 1881 1 2200 3
814 | 2 1882 1 3300 4
815 | 3 1880 0 3000 6
816 | 3 1881 0 2000 4
817 | 3 1882 0 1000 8
818 | end
819 | *- 转换数据
820 | reshape wide inc xx, i(id) j(year)
821 | ```
822 |
823 | `注意:` `reshape` 命令宽转长仅仅适用于变量以 文字+数字 形式命名
824 |
825 | ## 2.8 文字变量的处理
826 |
827 | ### 2.8.1 文字变量数值化
828 |
829 | 在一些数据的导入过程中,数值型的变量有可能被识别为文本型变量。在这种情况下,就需要将其转换为数值型变量,以方便后续的运算,可以使用 `destring` 命令进行转换。
830 |
831 | ```stata
832 | destring var, replace
833 | ```
834 |
835 | 意味着将被识别为文本型变量的 `var` 转换为数值型,并替代原来的值。
836 |
837 | 对于一些含有百分号的变量,也可以直接转换,比如。
838 |
839 | ```stata
840 | *- 生成数据
841 | clear
842 | input str6 Percent
843 | "10%"
844 | "20%"
845 | "30%"
846 | "40%"
847 | "50%"
848 | end
849 | browse
850 |
851 | *- 转换数据
852 | destring Percent, gen(Num) percent
853 | ```
854 |
855 | 这样新生成的变量 `Num` 就是百分比的数值型变量了。
856 |
857 | ### 2.8.2 文字变量的拆分
858 |
859 | 通过 `split` 函数,可以有效地拆分有规律的变量,比如。
860 |
861 | ```stata
862 | *- 生成变量
863 | clear
864 | input str18 City
865 | 台湾省台北市
866 | 台湾省高雄市
867 | 湖北省潜江市
868 | 湖北省武汉市
869 | 湖南省长沙市
870 | 四川省成都市
871 | end
872 |
873 | *- 从有规律的组合中拆分 省 与市区
874 | split City, parse("省")
875 | replace City1 = City1 + "省"
876 | rename City1 province
877 | rename City2 city
878 | ```
879 |
880 | 同样地,也可以通过 `substr()` 对文字变量进行截取,上述方法可以改写为如下。
881 |
882 | ```stata
883 | gen province1 = substr(City,1,9)
884 | gen city1 = substr(City,10,9)
885 | // 注意,每一个汉字算 3 个占位
886 | ```
887 |
888 | ### 2.8.3 处理文字变量的其他函数
889 |
890 | 可以通过 `help string functions` 查看所有的文字处理函数,这里介绍几个常用的。
891 |
892 | - 更改大小写
893 |
894 | ```stata
895 | dis lower("ASejksjdlwASD")
896 | dis upper("sadhASDkSss")
897 | ```
898 |
899 | - 测量文本长度
900 |
901 | ```stata
902 | dis length("汉字") // 一个汉字长度为 3
903 | dis length("English ") // 一个字母长度为 1,且空格为 1
904 | ```
905 |
906 | - 测量文字个数
907 |
908 | ```stata
909 | dis wordcount("汉字 English ") // 空格不作数
910 | ```
911 |
912 | - 匹配文本是否出现
913 |
914 | ```stata
915 | dis strmatch("xxx出生在中国湖北省潜江市", "潜江")
916 |
917 | dis strmatch("xxx出生在中国台湾省台北市", "台北市*")
918 | dis strmatch("xxx出生在中国台湾省台北市", "*台北市*")
919 |
920 | dis strmatch("Stata", "s")
921 | dis strmatch("Stata", "s")
922 | dis strmatch("Stata", "S")
923 | dis strmatch("Stata", "S*")
924 | ```
925 |
926 | 上述方法是区分大小写的,且匹配中文时需要在待匹配内容两侧加 * 。
927 |
928 | - 去除文本中空格的几种方法
929 |
930 | ```stata
931 | dis " 我还 在漂泊 你是错 过的烟火 "
932 |
933 | *- 去除两端空格
934 | dis strtrim(" 我还 在漂泊 你是错 过的烟火 ")
935 |
936 | *- 去除左边空格
937 | dis strltrim(" 我还 在漂泊 你是错 过的烟火 ")
938 |
939 | *- 去除右边空格
940 | dis strrtrim(" 我还 在漂泊 你是错 过的烟火 ")
941 |
942 | *- 去掉中间空格
943 | dis stritrim(" 我 还 在 漂泊 你 是错 过的烟火 ")
944 | help stritrim() // 将中间若干空格压缩成一个空格
945 |
946 | *- 若要去掉所有空格
947 | dis subinstr(" 我 还 在 漂泊 你 是错 过的烟火 "," ","",.)
948 | help subinstr() // 点表示替换所有空格
949 |
950 | dis subinstr(" 我 还 在 漂泊 你 是错 过的烟火 "," ","",2)
951 |
952 | dis subinstr(" 我 还 在 漂泊 你 是错 过的烟火 "," ","",4)
953 | ```
954 |
955 | 注意,以上方法都能配合 `gen` 生成新的变量。
956 |
957 | ### 2.8.4 正则表达
958 |
959 | `Stata` 支持正则表达,即通过特定的字符串规则提取文字变量中与规则对应的字符串。
960 |
961 | - 生成文本数据
962 |
963 | ```stata
964 | clear
965 | input str16 String
966 | "ab"
967 | "AA"
968 | "ABcd"
969 | "aab123"
970 | "AA133"
971 | "Cdf12345"
972 | "123"
973 | "错过的烟火"
974 | "红颜如霜123"
975 | end
976 | ```
977 |
978 | - 常用的操作有
979 |
980 | ```stata
981 | *- 提出所有数字
982 | gen Number = ustrregexs(0) if ustrregexm(String,"\d+")
983 |
984 | *- 提出所有小写字母
985 | gen LetterL = ustrregexs(0) if ustrregexm(String,"[a-z]+")
986 |
987 | *- 提出所有大写字母
988 | gen LetterU = ustrregexs(0) if ustrregexm(String,"[A-Z]+")
989 |
990 | *- 提出所有字母
991 | gen Letter = ustrregexs(0) if ustrregexm(String,"[a-zA-Z]+")
992 |
993 | *- 提出所有汉字
994 | gen Character = ustrregexs(0) if ustrregexm(String,"[\u4e00-\u9fa5]+")
995 |
996 | // 同时也可用于匹配身份证、邮政编码、网址、Email等
997 | ```
998 |
999 | 其余相关操作可以自行搜索发现,正则表达对文本的处理功能非常强大。
1000 |
--------------------------------------------------------------------------------