Zephyr中国跨国并购数据清洗实战:Python处理字段、币种与去重
简介这份资源为Zephyr数据库导出的中国跨国并购交易数据合集时间跨度覆盖2000年至2024年面向从事国际商务、产业经济、金融研究的高校师生与分析师可用于跨国并购趋势分析、案例筛选与实证研究。压缩包共2个文件以xls表格为主体数据文件另附html格式的数据来源说明整体约9.09MB体量适中便于本地整理与二次加工。表格字段通常涵盖并购时间、交易双方、行业分类、交易金额等维度适合按年份、行业或国别做分组统计与可视化。目前已有123人学习下载可作为论文选题、课题申报或行业报告的基础数据支撑帮助读者省去逐条搜集与清洗的重复工作快速进入建模与解读环节。1. 跨国并购数据拿到手第一件事为什么不是打开 ExcelZephyr 中国跨国并购数据2000-2024年这个压缩包名字已经把范围说得很清楚标的涉及中国、时间跨度二十五年、交易类型是并购。但真正做过跨国并购研究的人都知道这类数据最怕的不是缺年份而是口径不统一——同一笔交易在不同年份可能被记成不同状态金额单位可能混着人民币和美元标的行业分类可能中途换过标准。所以拿到压缩包之后第一件事不是双击打开 Excel 看有多少行而是先搞清楚它的字段结构、编码方式和缺失模式。这份数据适合三类人做学术实证的研究者、做行业复盘的投资分析师、以及需要快速摸清某条赛道跨境交易脉络的从业者。它解决的核心问题是把分散在公告、监管披露和交易数据库里的中国相关并购事件整理成一张可以按时间、行业、金额、交易状态筛选的结构化表。但前提是你得知道怎么把它从“能看”变成“能用”。2. 先拆字段再谈分析Zephyr 并购数据的结构长什么样2.1 交易主表、标的表和买方表的三角关系Zephyr 这类并购数据库通常不是一张大宽表而是拆成几张有关联的表。常见做法是一张交易主表记录交易编号、公告日期、完成日期、交易金额、交易状态一张标的表记录被收购方的名称、国家、行业代码一张买方表记录收购方名称、国家、最终母公司。三张表通过交易编号关联。如果你拿到的压缩包里只有一个 CSV那大概率是已经做过扁平化处理的宽表。这时候要重点看列名里有没有target_、acquiror_、deal_这样的前缀它们能帮你快速判断字段归属。我一般会先用 Python 把列名全部打印出来按前缀分组再决定后续怎么拆。import pandas as pd # 先只读列名不加载全部数据避免大文件卡死 cols pd.read_csv(zephyr_china_ma_2000_2024.csv, nrows0).columns.tolist() # 按前缀分组快速看清表结构 groups {} for c in cols: prefix c.split(_)[0] if _ in c else other groups.setdefault(prefix, []).append(c) for k, v in groups.items(): print(k, -, v)这段代码只读表头不占内存。nrows0是关键参数它让 pandas 只解析列名就返回。分组逻辑用第一个下划线前的词作为前缀如果列名本身没有下划线就归到other。跑完之后你会得到类似deal - [deal_id, deal_date, deal_value...]的输出这时候再决定哪些列需要类型转换、哪些列需要拆分。2.2 金额字段的币种和单位陷阱跨国并购数据里最容易被低估的坑就是金额字段。Zephyr 通常会给一个原始金额列和一个美元换算列但不同年份的换算汇率来源可能不同。更麻烦的是有些交易只披露了估值范围字段里会写成undisclosed或NA直接做sum()会静默跳过导致你算出来的总金额偏低。我一般会先做三件事第一统计金额列的缺失率第二看非缺失值里有没有非数字字符第三确认美元换算列是否已经覆盖了所有非缺失的原始金额。df pd.read_csv(zephyr_china_ma_2000_2024.csv, low_memoryFalse) # 缺失率 print(df[deal_value_usd].isna().mean()) # 看非数字样本 sample df[deal_value_usd].dropna().astype(str) non_numeric sample[~sample.str.match(r^[\d\.]$)] print(non_numeric.head(20)) # 原始金额非空但美元金额为空的行数 mask df[deal_value_original].notna() df[deal_value_usd].isna() print(mask.sum())low_memoryFalse是为了让 pandas 一次性推断类型避免分块读取时同一列在不同块里被推断成不同类型。str.match的正则只允许数字和小数点任何带逗号、带货币符号、带文字说明的值都会被筛出来。最后那个mask统计的是“有原始金额但没换算”的行数如果这个数很大说明你不能直接用美元列做全量分析。2.3 时间字段的格式统一与财年对齐2000 到 2024 年跨度很大日期格式可能混着YYYY-MM-DD、DD/MM/YYYY甚至YYYYMM。更隐蔽的问题是财年有些交易记录的是财年结束日有些是公告日有些是完成日。如果你要做年度趋势分析必须明确用哪个日期字段并且统一到日历年。常见做法是优先用deal_completed_date缺失时回退到deal_announced_date再缺失才用deal_fiscal_year_end。回退逻辑要显式写出来不能默认fillna一个了事。df[date_final] pd.to_datetime(df[deal_completed_date], errorscoerce) df[date_final] df[date_final].fillna( pd.to_datetime(df[deal_announced_date], errorscoerce) ) df[date_final] df[date_final].fillna( pd.to_datetime(df[deal_fiscal_year_end], errorscoerce) ) df[year] df[date_final].dt.year print(df[year].value_counts().sort_index())errorscoerce让无法解析的值变成NaT而不是报错这样你可以先跑通再回头处理异常。三次fillna的顺序就是优先级顺序。最后按年统计如果某几年数量异常少大概率是那几年的日期字段格式有问题需要单独回去看原始值。3. 从原始表到可分析样本清洗与筛选的五个关键动作3.1 交易状态筛选别把传闻和意向书算进成交Zephyr 的交易状态字段通常有Completed、Announced、Pending、Rumour、Withdrawn等值。做实证研究时如果你要分析“实际发生的并购”就必须只保留Completed。但很多人会忽略Announced里有一部分后来变成了Completed而Completed里也可能包含后来又被撤销的。我一般会先看状态字段的取值分布再决定筛选策略。如果要做事件研究用公告日如果要做财务绩效分析用完成日且状态为Completed。print(df[deal_status].value_counts(dropnaFalse)) # 只保留已完成交易 df_completed df[df[deal_status].str.lower() completed].copy() # 检查是否有完成日期缺失的已完成交易 print(df_completed[deal_completed_date].isna().sum())str.lower()是为了防止大小写不一致。dropnaFalse让缺失值也出现在统计里避免你误以为没有缺失。如果已完成交易里还有大量完成日期缺失说明状态字段和日期字段的维护质量不一致需要人工抽查。3.2 标的国别与中国相关的判定口径标题写的是“中国跨国并购”但“中国相关”可以有三种口径标的在中国、买方在中国、或者最终母公司在中国。Zephyr 通常会给target_country、acquiror_country和acquiror_ultimate_parent_country三个字段。如果你只按标的国别筛会漏掉中国公司收购海外资产的情况如果只按买方国别筛会漏掉外资收购中国资产的情况。常见做法是先明确你的研究问题。如果是“中国企业出海并购”用买方国别如果是“外资入境并购”用标的国别如果是“所有涉及中国的跨境交易”三个字段取并集。china_mask ( (df[target_country] China) | (df[acquiror_country] China) | (df[acquiror_ultimate_parent_country] China) ) df_china df[china_mask].copy() print(df_china.shape)三个条件用|连接只要任一满足就保留。注意这里没有用str.contains因为国别字段通常是标准化的国家名精确匹配更安全。跑完之后对比一下只按单一字段筛的结果差异行数就是你需要人工判断的部分。3.3 行业分类的版本对齐2000 到 2024 年行业分类标准可能从 GICS 换到 NAICS 再换到 Zephyr 自己的分类。如果你直接按target_industry分组做趋势会发现同一行业在不同年份叫法不同。我一般会先看行业字段的唯一值数量如果超过 200 个说明粒度太细需要映射到一级或二级分类。print(df_china[target_industry].nunique()) print(df_china[target_industry].value_counts().head(30))如果唯一值太多常见做法是保留前 20 个高频行业其余归为Other。或者找一份行业映射表把细分类别归并到大类。映射表可以手工建也可以用关键词匹配但手工建更可控。3.4 去重同一交易的多条记录怎么合并跨国并购数据里同一笔交易可能因为多次公告、多次修订而出现多条记录。Zephyr 通常会给一个deal_id但有时候同一deal_id下会有不同版本的记录。我一般会按deal_id分组保留完成日期最新或状态为Completed的那条。df_china df_china.sort_values(date_final, ascendingFalse) df_dedup df_china.drop_duplicates(subset[deal_id], keepfirst) print(df_china.shape, -, df_dedup.shape)sort_values把最新日期排前面drop_duplicates的keepfirst就保留了最新那条。如果deal_id有缺失需要先用其他字段组合生成一个临时唯一键比如acquiror_name target_name year。3.5 缺失值处理什么时候该删什么时候该填金额和行业是并购分析里最常缺失的两个字段。我的原则是金额缺失超过 40% 的年份不做金额相关的趋势分析行业缺失超过 20% 的样本单独归为Unknown而不是直接删。直接删会引入选择偏差因为缺失往往不是随机的——小交易更可能不披露金额。# 按年统计金额缺失率 missing_by_year df_dedup.groupby(year)[deal_value_usd].apply(lambda x: x.isna().mean()) print(missing_by_year) # 行业缺失归为 Unknown df_dedup[target_industry] df_dedup[target_industry].fillna(Unknown)groupby加apply可以按年看缺失率的变化趋势。如果某几年缺失率突然飙升说明那几年的数据采集口径可能变了需要在论文或报告里注明。4. 避坑与排查Zephyr 中国并购数据最常见的五个翻车点4.1 现象按年统计交易数量某几年突然断崖式下跌原因日期字段在那几年用了不同的格式pd.to_datetime解析失败后变成NaT被value_counts静默排除。解决先看date_final的缺失率按年分布再回去检查原始日期列的格式。如果原始列是YYYYMM这种没有日的格式需要手动补一个01再解析。4.2 现象总交易金额算出来比预期低很多原因金额字段里混着undisclosed、NA、-等占位符astype(float)会报错但如果你用pd.to_numeric(errorscoerce)这些值会变成NaN被跳过。解决先统计非数字样本确认占位符种类再决定是删还是填。如果要做总金额必须明确说明“基于已披露金额的交易”。4.3 现象同一笔交易在数据里出现两次金额还不一样原因一次是公告时的预估金额一次是完成时的最终金额。Zephyr 可能保留了两条记录。解决按deal_id去重保留完成日期最新的那条。如果deal_id也重复用acquiror_name target_name year组合去重。4.4 现象行业趋势图里某个行业在中间几年消失原因行业分类标准换了旧名称不再使用。解决建一张映射表把旧名称映射到新名称或者统一归并到一级分类。映射表要保留原始字段方便回溯。4.5 现象中国买方收购海外资产但标的国别字段显示的是海外原因这是正常现象。如果你只按target_country China筛选就会漏掉出海并购。解决明确你的筛选口径三个国别字段取并集并在方法部分写清楚。5. 用 Python 做一份可复现的年度趋势与行业分布5.1 年度趋势交易数量与金额的双轴图清洗完之后最直接的验证方式就是画年度趋势。交易数量用柱状图金额用折线图双轴展示。这样能一眼看出“数量多但金额小”和“数量少但金额大”的年份差异。import matplotlib.pyplot as plt yearly df_dedup.groupby(year).agg( deal_count(deal_id, count), total_value(deal_value_usd, sum) ).reset_index() fig, ax1 plt.subplots(figsize(12, 5)) ax1.bar(yearly[year], yearly[deal_count], color#4C72B0, alpha0.7, labelDeal Count) ax1.set_ylabel(Deal Count) ax1.set_xlabel(Year) ax2 ax1.twinx() ax2.plot(yearly[year], yearly[total_value], color#DD8452, markero, labelTotal Value (USD)) ax2.set_ylabel(Total Value (USD)) plt.title(China Cross-border MA: 2000-2024) fig.legend(locupper left, bbox_to_anchor(0.1, 0.9)) plt.tight_layout() plt.savefig(yearly_trend.png, dpi150)groupby(year)后agg同时算数量和金额。twinx()创建共享 x 轴的双 y 轴。bbox_to_anchor调整图例位置避免遮挡数据。保存时dpi150保证清晰度。跑完这张图你就能快速判断数据在时间维度上是否合理。5.2 行业分布Top 15 行业的交易金额占比行业分布用横向条形图更易读尤其是行业名称较长的时候。先按行业汇总金额取前 15 个再算占比。industry df_dedup.groupby(target_industry)[deal_value_usd].sum() industry industry.sort_values(ascendingFalse).head(15) industry_pct industry / df_dedup[deal_value_usd].sum() * 100 fig, ax plt.subplots(figsize(10, 6)) industry_pct.sort_values().plot(kindbarh, axax, color#55A868) ax.set_xlabel(Share of Total Deal Value (%)) ax.set_title(Top 15 Target Industries by Deal Value) plt.tight_layout() plt.savefig(industry_dist.png, dpi150)sort_values(ascendingFalse).head(15)取金额最大的 15 个行业。industry_pct算的是占总金额的比例不是占交易数量的比例。barh是横向条形图sort_values()默认升序这样最大的行业会显示在最上面。如果某个行业占比异常高需要回去检查是不是有几笔超大交易集中在这个行业。5.3 用交叉表验证“出海”与“入境”的年份差异最后一步验证按年份和交易方向做交叉表。交易方向可以用标的国别和买方国别组合判断标的在中国、买方在海外是入境标的在海外、买方在中国是出海。def deal_direction(row): if row[target_country] China and row[acquiror_country] ! China: return Inbound elif row[target_country] ! China and row[acquiror_country] China: return Outbound else: return Other df_dedup[direction] df_dedup.apply(deal_direction, axis1) cross pd.crosstab(df_dedup[year], df_dedup[direction]) print(cross.tail(10))apply(axis1)逐行判断方向。pd.crosstab生成年份和方向的交叉表。tail(10)看最近十年。如果Other占比很高说明你的国别字段可能有缺失或口径不一致需要回去检查。5.4 一个我踩过的坑不要用sum()直接算缺失金额早期我做年度金额趋势时直接df.groupby(year)[deal_value_usd].sum()结果某几年金额特别低。后来才发现那几年缺失率超过 50%sum()默认跳过NaN导致总金额被低估。正确做法是同时输出缺失率或者在图表里标注“基于已披露金额”。这个习惯我保留到现在任何金额聚合旁边必须有一列缺失率。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

C语言链表从入门到实操:指针、内存管理与增删实现

C语言链表从入门到实操:指针、内存管理与增删实现

写这篇文章的起因有点现实——我见过太多初学者把链表当成"面试背题",却在真正需要它的时候手足无措。链表是 C 语言里绕不开的核心数据结构,它和数组一起,构成理解更复杂数据结构(栈、队列、树、图)的两根拐…

2026/10/12 16:04:33 阅读更多 →
TLS 1.3配置审计、证书锁定绕过与中间人攻击实战全记录

TLS 1.3配置审计、证书锁定绕过与中间人攻击实战全记录

我们内部做了一次针对某业务系统的传输安全深度评估,范围限制在传输层,核心任务就三条:把 TLS 1.3 的配置翻个底朝天、试着绕过证书锁定、走一遍中间人攻击的标准套路。说实话,这类活儿在安全圈里不算少见,但真正跑完一…

2026/10/12 17:00:19 阅读更多 →
Unity UI形状与分辨率适配:从锚点到SafeArea

Unity UI形状与分辨率适配:从锚点到SafeArea

Unity开发里,自定义游戏界面形状/分辨率是个埋了很多暗坑的主题。我前阵子接手一个模拟项目X,美术给了一套圆形小地图、圆角按钮和不规则面板的设计稿,第一版是在固定模拟分辨率下做出来的,看着很正常。结果一上真机,长…

2026/10/12 17:53:24 阅读更多 →

最新新闻

JSTL 标签库实战:从脚本片段到标签封装的核心技巧

JSTL 标签库实战:从脚本片段到标签封装的核心技巧

1. 从脚本片段到标签封装&#xff1a;JSTL 到底解决了什么问题很多人第一次接触 JSTL&#xff0c;是在维护一个老项目的时候。打开 JSP 文件&#xff0c;满屏的<% for(...) { %>、<% if(...) { %>和<% request.getAttribute("xxx") %>&#xff0c;…

2026/10/12 17:55:23 阅读更多 →
告别API依赖!GitHub上那些可以完全本地运行的优质开源AI项目盘点:用TaoToken统一Key打通本地与云端

告别API依赖!GitHub上那些可以完全本地运行的优质开源AI项目盘点:用TaoToken统一Key打通本地与云端

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 17:55:23 阅读更多 →
共享单车数据集VOC格式实战:从标注解析到YOLO训练全流程

共享单车数据集VOC格式实战:从标注解析到YOLO训练全流程

简介&#xff1a;这份共享单车数据集采用VOC格式整理&#xff0c;面向从事目标检测算法练习、课程设计或毕业设计的学生与开发者&#xff0c;可用于训练和验证单车识别模型&#xff0c;解决真实街景中共享单车标注样本不足的问题。压缩包共272个文件&#xff0c;包含136张jpg实…

2026/10/12 17:55:23 阅读更多 →
Python机器学习预测电影首周票房实战指南

Python机器学习预测电影首周票房实战指南

简介&#xff1a;这是一套面向计算机专业本科生的机器学习实战项目资源&#xff0c;聚焦电影票房预测这一典型回归建模任务&#xff0c;适用于毕业设计、课程设计及期末大作业场景。资源包含完整可运行的Python源码、清洗后的TMDB 5000电影数据集&#xff08;含credits与movies…

2026/10/12 17:55:23 阅读更多 →
Jupyter Notebook虚拟环境配置指南:Kernel与conda/venv绑定方法

Jupyter Notebook虚拟环境配置指南:Kernel与conda/venv绑定方法

1. 先搞清楚&#xff1a;为什么 Notebook 老是"用错环境"我最初接触这个问题&#xff0c;是因为在同一个项目里同时跑了两个不同版本的深度学习框架&#xff0c;一个依赖 Python 3.8&#xff0c;一个依赖 Python 3.10。Jupyter Notebook 默认启动时用的是系统 PATH 里…

2026/10/12 17:55:23 阅读更多 →
Tesseract OCR中文识别实战:安装、调优与避坑指南

Tesseract OCR中文识别实战:安装、调优与避坑指南

简介&#xff1a;Tesseract OCR 安装包与中文语言包面向需要在本地完成图片文字识别的开发者、测试人员及自动化办公用户&#xff0c;尤其适合用 Python 调用 OCR 引擎处理中文文档、票据或截图的人群。压缩包共 723 个文件&#xff0c;约 36.01MB&#xff0c;以 C 源码&#x…

2026/10/12 17:54:23 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天&#xff0c;画面可以做到绝对的锐利、平滑与无瑕。然而&#xff0c;当一张秋日手账插画或拍立得照片过于“平整无瑕”时&#xff0c;往往会散发出一种冰冷生硬的“数码塑料感&#xff08;Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中&#xff0c;横排&#xff08;Horizontal Layout&#xff09;早已经成为了绝对的主流。然而&#xff0c;当我们翻开泛黄的线装古籍、宋版木刻诗集&#xff0c;或是欣赏一张茶道雅集的手写便签时&#xff0c;那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点&#xff0c;很多人心里都会悄悄亮起一盏警示灯。 在心理学上&#xff0c;这种现象有一个专门的称谓——“周日夜晚焦虑症&#xff08;Sunday Scaries&#xff09;”。明天又是周一&#xff0c;闹钟又要重新在七点响彻卧房&#xff1b;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →