news 2026/3/1 3:48:27

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/2/25 6:03:33

附完整命令:一步步搭建属于你的开机启动服务

附完整命令&#xff1a;一步步搭建属于你的开机启动服务 你是否遇到过这样的问题&#xff1a;写好了自动化脚本&#xff0c;每次重启后却要手动运行&#xff1f;或者部署了一个后台服务&#xff0c;希望它像系统服务一样随机器启动自动拉起&#xff1f;别担心&#xff0c;这不…

作者头像 李华
网站建设 2026/2/22 9:39:51

从上传到下载,全程中文界面的AI抠图实战记录

从上传到下载&#xff0c;全程中文界面的AI抠图实战记录 1. 这不是“又一个抠图工具”&#xff0c;而是一次真正省心的图像处理体验 你有没有过这样的经历&#xff1a; 想给一张人像换背景&#xff0c;打开PS折腾半小时&#xff0c;还是抠不干净发丝&#xff1b; 电商运营要批…

作者头像 李华
网站建设 2026/2/26 0:09:09

告别复杂配置!VibeThinker-1.5B本地部署保姆级指南

告别复杂配置&#xff01;VibeThinker-1.5B本地部署保姆级指南 你是否试过下载一个AI模型镜像&#xff0c;点开文档却看到满屏的conda环境、CUDA版本校验、依赖冲突报错、端口占用排查……最后关掉终端&#xff0c;默默打开网页版API&#xff1f; VibeThinker-1.5B 不是那样。…

作者头像 李华
网站建设 2026/2/27 4:13:26

Qwen3-4B-Instruct效果实录:根据UML类图描述生成Spring Boot基础工程

Qwen3-4B-Instruct效果实录&#xff1a;根据UML类图描述生成Spring Boot基础工程 1. 这不是“写代码”&#xff0c;而是“建工程”——一次真实的AI工程化实践 你有没有试过&#xff0c;把一张手绘的UML类图拍下来&#xff0c;发给AI&#xff0c;然后它直接给你生成一个可运行…

作者头像 李华
网站建设 2026/3/1 3:09:05

分段调试技巧曝光!用VibeVoice-TTS精准控制每句语音输出

分段调试技巧曝光&#xff01;用VibeVoice-TTS精准控制每句语音输出 在制作有声书、播客脚本或虚拟角色对话时&#xff0c;你是否遇到过这样的困扰&#xff1a;整段文本一次性合成后&#xff0c;发现第三段语气生硬、第五段语速偏快、第七段音色切换错误——可重来一次又要等两…

作者头像 李华
网站建设 2026/2/27 12:33:58

让 AI 也能当“反洗钱专家“——一个通俗易懂的模型训练故事

故事的开端&#xff1a;为什么要做这件事?想象一下,你是一家银行的合规专员。每天要面对厚厚的反洗钱法规文件,还要分析各种复杂的可疑交易案例。有些问题特别棘手:法律条文晦涩难懂,一个条款套着另一个条款真实的洗钱案例千奇百怪,要从蛛丝马迹中发现问题有时候一个问题涉及好…

作者头像 李华