news 2026/2/10 4:33:12

Stata 大规模数据缩尾处理:winsor2和gstats_winsor哪个更快?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Stata 大规模数据缩尾处理:winsor2和gstats_winsor哪个更快?

温馨提示:若页面不能正常显示数学公式和代码,请阅读原文获得更好的阅读体验。

作者:丁闪闪 (连享会)
邮箱:lianxhcn@163.com

  • Title: Stata 大规模数据缩尾处理:winsor2和gstats_winsor哪个更快?
  • Keywords: 离群值, winsorize, winsorizing, Stata数据处理, 数据清洗, 奇异值, outliers

winsor(缩尾)本身的原理非常简单:把极端的离群值"压回"到某个分位点边界上。真正让人头疼的往往不是概念,而是当数据规模变大之后——同样是1%/99%winsor,有的写法几分钟,有的写法只需几秒甚至更快。

本文的目标是:

  • 在一份超大规模面板数据上,对比几种常见缩尾命令的运行速度
  • 顺带把egenwinsorwinsor2gstats winsor的基本语法捋清楚
  • timer命令做一个相对公平的耗时对比

我们发现:gstats winsor在大规模数据上是最快的。在本文的模拟分析中,gstats winsor处理2,400 万行数据只需 3-4 秒;而winsor2egen ... pctile()处理同样的数据需要约 40-50 秒。

若是处理日常数据,比如样本数不超过 20 万行,上述命令都可以在 1 秒内完成 (约 0.3-0.5 秒)。此时,选择哪个命令就仅仅是个人偏好的问题了。

因此,日常缩尾处理,建议使用winsor2,大规模数据 (超过 100 万行) 则推荐使用gstats winsor。注意,安装gtools包后才能使用gstats winsor

1. 何谓缩尾处理 (winsor)?

给定连续变量 xx(例如日收益率),以 1%/99% 缩尾为例:

  • 设 q0.01q0.01​ 为 1% 分位点,q0.99q0.99​ 为 99% 分位点
  • winsor 的核心操作是替换(replace):把落在两端尾部的极端值“压回”到边界分位点上,因此不会减少样本量
  • winsor 后的新变量 x(w)x(w) 定义为

x(w)=min⁡(max⁡(x,q0.01),q0.99)x(w)=min(max(x,q0.01​),q0.99​)

更直观地写成分段函数也可以:

x(w)={q0.01,x<q0.01 x,q0.01≤x≤q0.99 q0.99,x>q0.99x(w)={q0.01​,​x<q0.01​ x,​q0.01​≤x≤q0.99​ q0.99​,​x>q0.99​​

金融面板里更常见的是“按年 winsor”:在每一年 tt 内分别计算分位点 q0.01,tq0.01,t​ 与 q0.99,tq0.99,t​,并做同样的替换:

x(w)∗it=min⁡(max⁡(x∗it,q0.01,t),q0.99,t)x(w)∗it=min(max(x∗it,q0.01,t​),q0.99,t​)

对比一下概念上很容易混淆的trim(截尾):trim 是把两端极端值直接删掉(在 Stata 中通常是设为 missing),因此会损失样本量;而 winsor 只是替换极端值,不会减少观测数。

参见:袁煜玲, 2021, winsor2:离群值和异常值的缩尾处理.

1.1 最简单的 winsor 操作长什么样?

为了先有一个直观感受,下面用最常见的winsor2举例(连玉君团队维护的外部命令,国内实证中使用非常普遍,入门介绍可参见:袁煜玲 (2021) 的推文)。(连享会)

* 安装 winsor2 ssc install winsor2, replace * 1%/99% winsor(全样本),替换原变量 (默认 cuts(1 99)) winsor2 x, replace winsor2 x1 x2 x3, replace * 按年 winsor, 另存为新变量 stock_return_w winsor2 x, by(year) suffix(_w) * 人为指定分位点 winsor2 x, cuts(5 95) replace

1.2 本文会用到的几个命令

后文的对比主要围绕以下几类做法:

  • egen ... pctile():手动计算分位点,再用replace截断(透明,但通常最慢)
  • winsor(Nick Cox):经典社区命令,语义清晰,常用于单变量缩尾(Stata)
  • winsor2(Yujun Lian):支持 varlist、分组 winsor、批量处理,是金融实证的"工作流命令"(连享会)
  • gstats winsor(gtools):强调大数据场景性能优化,通常是速度最有优势的方案之一 (gtools.readthedocs.io)

如果你尚未安装上述命令,可以使用以下命令安装:

ssc install winsor, replace ssc install winsor2, replace ssc install gtools, replace

2. 数据模拟与计时方案

2.1 模拟:5,000 家公司 × 20 年 × 240 交易日

你给定的规模是:

  • N=5000N=5000 家公司
  • T=20T=20 年
  • 每年 D=240D=240 个交易日
  • 总样本量:N×T×D=24,000,000N×T×D=24,000,000(2,400 万行)

并且stock_return近似正态分布,但有约 2% 的"异常冲击"。

下面这段代码可以直接复制运行。注意:2,400 万行对内存要求较高,如果机器顶不住,可以把Nfirm, 或Nday改成小一点的数值。

**************************************************** * Simulate: N firms × T years × D trading days * stock_return ~ Normal, with 2% outliers (mixture) **************************************************** clear all set more off set seed 20260121 *-------------------------------------------------- * 基本参数设定 *-------------------------------------------------- local Nfirm = 5000 local Tyear = 20 local Nday = 240 *-------------------------------------------------- * Step 1: 先生成 firm 层面的数据(Nfirm 行) *-------------------------------------------------- set obs `Nfirm' gen int firm_id = _n *-------------------------------------------------- * Step 2: 扩张到 firm-year(每家 firm 复制 Tyear 次) * 这里使用 expand *-------------------------------------------------- expand `Tyear' * 在 firm 内生成 year_index: 2001...2020 bysort firm_id: gen int year_index = 2000 + _n *-------------------------------------------------- * Step 3: 扩张到 firm-year-day(每个 firm-year 复制 Nday 次) *-------------------------------------------------- expand `Nday' * 在 (firm_id year) 内生成 trading_day: 1...Nday bysort firm_id year: gen int trading_day = _n *-------------------------------------------------- * Step 4: 生成收益率:主体为 N(0, 0.02^2) * 并注入 2% 离群冲击:叠加 N(0, 0.80^2), N(0, 1.50^2) gen double stock_return = rnormal(0, 0.02) gen double u = runiform() replace stock_return = stock_return + rnormal(0, 0.80) if u < 0.01 replace stock_return = stock_return + rnormal(0, 1.50) if u < 0.99 drop u *-------------------------------------------------- * Step 5: 存储数据 *-------------------------------------------------- order firm_id year trading_day stock_return save "stock_data_temp.dta", replace

数据概况如下:

. sum Variable | Obs Mean Std. dev. Min Max -------------+------------------------------------------------------ firm_id | 24,000,000 2500.5 1443.376 1 5000 year_index | 24,000,000 2010.5 5.766281 2001 2020 trading_day | 24,000,000 120.5 69.28143 1 240 stock_return | 24,000,000 .0001295 1.494831 -8.108931 8.017766 . dir stock_data_temp* 320.4M 1/21/26 19:40 stock_data_temp.dta

可见,模拟生成的数据包含 2,400 万行,涵盖 5,000 家公司、20 年、每年 240 个交易日的股票收益率。若存储为 Stata 数据文件,文件大小约为 320 MB。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/29 0:23:12

用GPEN镜像修复爷爷奶奶的老照片,家人感动哭了

用GPEN镜像修复爷爷奶奶的老照片&#xff0c;家人感动哭了 那天整理老相册时&#xff0c;我翻出一叠泛黄卷边的黑白照片&#xff1a;爷爷穿着中山装站在单位门口&#xff0c;奶奶扎着两条麻花辫在校园梧桐树下微笑。照片上布满划痕、噪点和模糊的轮廓&#xff0c;连他们眼角的…

作者头像 李华
网站建设 2026/2/1 6:17:53

RetinaFace在工业质检中的延伸:PCB板上人脸形变检测辅助定位算法

RetinaFace在工业质检中的延伸&#xff1a;PCB板上人脸形变检测辅助定位算法 你可能第一眼会疑惑&#xff1a;人脸检测模型&#xff0c;怎么用在电路板质检上&#xff1f;这听起来像把咖啡机拿来修汽车——风马牛不相及。但事实是&#xff0c;RetinaFace 不只是“找人脸”的工…

作者头像 李华
网站建设 2026/2/4 21:35:06

ms-swift云端部署教程:阿里云ECS实例操作指南

ms-swift云端部署教程&#xff1a;阿里云ECS实例操作指南 1. 为什么选择ms-swift进行云端大模型微调&#xff1f; 在实际工程落地中&#xff0c;很多团队面临一个共同难题&#xff1a;本地GPU资源有限&#xff0c;但又需要快速验证大模型微调效果、构建定制化AI能力。这时&am…

作者头像 李华
网站建设 2026/1/30 18:37:46

CogVideoX-2b视觉盛宴:多风格AI生成视频作品集锦

CogVideoX-2b视觉盛宴&#xff1a;多风格AI生成视频作品集锦 1. 这不是“又一个文生视频工具”&#xff0c;而是一台装在服务器里的微型电影工厂 你有没有试过&#xff0c;只用一句话&#xff0c;就让一张静态画面活起来&#xff1f;不是加个滤镜、不是套个模板&#xff0c;而…

作者头像 李华
网站建设 2026/2/6 17:32:45

YOLOv10导出Engine文件,支持端到端部署落地

YOLOv10导出Engine文件&#xff0c;支持端到端部署落地 1. 为什么必须导出为Engine&#xff1f;——从模型到产品的关键一跃 你可能已经用yolo predict命令跑通了YOLOv10的检测效果&#xff1a;输入一张图&#xff0c;几秒内框出人、车、猫狗&#xff0c;AP值亮眼&#xff0c…

作者头像 李华