├── 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 | ![](../../images/onetext/figure1.png) 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 | ![](../../images/onetext/figure2.png) 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 | ![](../../images/onetext/figure3.png) 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 | --------------------------------------------------------------------------------