CrashData:R语言清洗航空事故数据的完整实践指南
简介CrashData 是一份面向数据分析与航空安全研究者的 R 语言数据采集脚本资源用于从 planecrashinfo.com 逐年抓取飞机失事的历史记录解决公开事故数据分散、难以批量获取的问题。作者以略显取巧但可用的方式将网页内容整理为规整的 data.frame方便后续做趋势分析、可视化或统计建模适合具备 R 基础、关注航空事故数据的中级学习者。压缩包共 2 个文件包含 1 个 R 脚本与 1 个 md 说明文档整体仅 1KB轻量易读脚本负责抓取与结构化说明文档交代用法与背景。目前已有 1422 人学习下载。读者可直接获得可复用的数据抓取逻辑、逐年提取思路以及开箱即用的数据框输出省去自行解析网页的时间也能在此基础上扩展字段、清洗缺失值或接入自己的分析流程是入门网络数据采集与航空事故研究的实用起点。1. 从公开事故记录到可分析数据集CrashData 到底解决什么问题做航空安全分析、事故统计建模或者时间序列研究的人大概率都遇到过同一个尴尬网上能查到的坠机信息不少但真要拉一份结构化的历史数据下来要么字段残缺要么格式混乱要么得手动一页页抄。CrashData 这个资源包瞄准的就是这个痛点——它把 planecrashinfo.com 上公开的飞机失事历史记录整理成一份可以直接用 R 加载、清洗、分析的本地数据集。换句话说它不教你造轮子而是把轮子拆好、标好尺寸递到你手上。这份资源适合三类人一是做航空安全或事故频率建模的研究者需要一份可复现的底层数据二是学 R 语言数据清洗的练习者想拿真实脏数据练手三是做可视化或统计报告的人想快速拿到一份带时间、地点、机型、伤亡人数的结构化表。它不涉及任何敏感信息全部来自公开事故记录重点在于“把散落的网页表格变成能跑代码的数据框”。下面我从数据获取、字段解析、清洗逻辑到常见翻车点一步步拆开讲。2. 数据获取与原始结构从网页表格到本地文件的完整链路2.1 为什么选 planecrashinfo.com 作为数据源公开的航空事故记录来源不少但 planecrashinfo.com 的特点是时间跨度长、字段相对固定、页面结构简单。它按年份组织事故列表每条记录通常包含日期、地点、机型、注册号、运营商、死亡人数、事故描述等。对于用 R 做分析的人来说这种“一个年份一个页面、表格行列规整”的结构比那些需要登录、分页、动态加载的站点友好得多。常见做法是先用rvest把每个年份页面的表格抓下来再合并成一个大表。但这里有个前提你得先确认目标页面的 HTML 结构是否稳定。我一般会先抓一年看看列数和列名再决定是直接读table还是逐行解析tr。CrashData 资源包里已经包含了整理好的原始抓取结果和对应的 R 脚本省去了从零写爬虫的环节。如果你要自己复现建议先检查页面是否有反爬限制以及年份覆盖范围是否满足你的研究区间。2.2 用 R 读取和合并多年度数据假设你已经把各年份的页面保存为本地 HTML 文件或者直接用read_html()在线读取下面这段代码展示了如何把多个年份的表格合并成一个数据框。注意年份范围要根据你的实际需求调整不要盲目全量抓取。library(rvest) library(dplyr) library(purrr) # 定义要抓取的年份范围建议先小范围测试 years - 2000:2020 # 用一个函数封装单年抓取逻辑 fetch_year - function(year) { url - paste0(http://www.planecrashinfo.com/, year, /, year, .htm) page - read_html(url) # 抓取页面中的表格通常第一个表格就是事故列表 tbl - page %% html_node(table) %% html_table(fill TRUE) # 加上年份列方便后续合并 tbl$year - year return(tbl) } # 批量抓取用 possibly 避免单年失败导致整体中断 safe_fetch - possibly(fetch_year, otherwise NULL) all_data - map(years, safe_fetch) %% compact() %% bind_rows()这段代码的核心逻辑是“分年抓取、统一加年份列、最后按行合并”。possibly()的作用是容错——某一年页面结构变了或者网络超时不会让整个循环崩掉而是返回 NULL 被compact()过滤掉。参数方面html_table(fill TRUE)里的fill很关键因为原始表格可能存在空单元格不加这个参数会报错或者列数对不齐。年份范围建议先跑 3 到 5 年确认字段一致后再扩大。2.3 字段映射与类型转换的注意事项抓下来的原始表格通常是字符型列名也可能带空格或特殊符号。直接拿来分析会很难受所以需要做一轮重命名和类型转换。常见做法是把日期列转成Date类型把死亡人数转成数值型把地点和运营商保留为字符型。这里有个坑原始数据里的日期格式可能是“Jan 1, 2000”这种直接as.Date()会返回 NA需要指定格式或者用lubridate的mdy()。library(lubridate) clean_data - all_data %% rename( date_raw Date, location Location, operator Operator, aircraft Aircraft, fatalities Fatalities ) %% mutate( # 日期解析注意原始格式可能是 Jan 1, 2000 date mdy(date_raw), # 死亡人数可能包含 123 (123) 这种格式需要提取数字 fatalities_num as.numeric(str_extract(fatalities, \\d)), # 年份从日期中提取用于分组统计 year year(date) ) %% filter(!is.na(date)) # 去掉日期解析失败的行这段清洗逻辑的重点是“先重命名、再解析、最后过滤”。mdy()能自动识别月日年顺序比as.Date()省心。str_extract()用来从混合字符串里抠出第一个数字因为原始死亡人数字段有时会写成“123 (123)”表示总死亡和机上死亡。过滤掉日期解析失败的行是必要的否则后续按时间聚合会出错。如果你发现某一年大量日期解析失败大概率是页面格式变了需要单独检查那一年的原始 HTML。3. 数据清洗与特征工程把脏表变成可建模的数据框3.1 处理缺失值与重复记录的策略公开事故记录里缺失值很常见尤其是早期年份的运营商、机型字段。直接删行会损失样本全部填充又可能引入偏差。我一般会分字段处理日期和死亡人数这种关键字段缺失就删地点和运营商这种描述性字段缺失就保留 NA分析时再按需过滤。重复记录方面同一年份页面里偶尔会出现同一事故被列两次的情况通常是因为表格跨页或者抓取时重复读取。可以用日期加地点加机型做联合去重。dedup_data - clean_data %% # 关键字段缺失直接剔除 filter(!is.na(date), !is.na(fatalities_num)) %% # 按日期、地点、机型联合去重保留第一条 distinct(date, location, aircraft, .keep_all TRUE)distinct()的参数.keep_all TRUE表示保留所有列只按指定列去重。这里选日期、地点、机型三个字段是因为它们组合起来基本能唯一标识一次事故。如果你发现去重后样本量骤降可能是某个字段的格式不统一比如地点里多了空格或者大小写不一致需要先做标准化。3.2 构造时间维度特征年份、十年期与事故频率做时间序列分析时原始日期粒度太细通常需要聚合到年或十年。用lubridate可以很方便地提取年份、月份、十年期。事故频率则可以用count()按年份统计再和总航班量或乘客数做归一化——不过后者需要额外数据源CrashData 本身不包含。这里先展示如何构造年份和十年期字段以及如何计算每年的每起事故平均死亡人数。feature_data - dedup_data %% mutate( year year(date), decade floor(year / 10) * 10, month month(date, label TRUE) ) %% group_by(year) %% mutate( accidents_per_year n(), avg_fatalities mean(fatalities_num, na.rm TRUE) ) %% ungroup()floor(year / 10) * 10是构造十年期的常用技巧比如 1987 年归到 1980 年代。group_by()加mutate()可以在不丢失原始行的情况下添加聚合特征比summarise()更适合后续做逐行分析。na.rm TRUE在计算均值时排除缺失值避免整列变 NA。如果你要做事故频率的年度趋势图直接用count(feature_data, year)更简洁。3.3 地点与运营商的文本标准化地点字段经常包含国家、城市、机场名混在一起的情况运营商字段可能有缩写和全称并存。如果要做分组统计不标准化会导致同一个实体被拆成多个类别。常见做法是用stringr做大小写统一、去空格、替换常见缩写。比如把“U.S.”和“United States”统一成“USA”把“Intl”和“International”统一。这一步没有万能规则需要根据你的分析目标决定粒度。library(stringr) normalized_data - feature_data %% mutate( location_clean location %% str_to_upper() %% str_replace_all(U\\.S\\., USA) %% str_replace_all(UNITED STATES, USA) %% str_trim(), operator_clean operator %% str_to_upper() %% str_replace_all(AIRLINES, AIR) %% str_trim() )这段代码展示了文本标准化的基本套路先统一大写再替换常见变体最后去首尾空格。str_replace_all()支持正则所以“U\.S\.”里的反斜杠是转义点号。注意不要过度标准化比如把“AIR”和“AIRWAYS”合并可能会丢失信息。我一般会先跑一遍table()看看有哪些高频值再决定替换规则。4. 避坑与排查抓取和清洗中最容易翻车的五个点4.1 页面结构变动导致表格列错位现象某一年抓下来的数据框列数和列名跟其他年份对不上合并时报错或者出现大量 NA。原因planecrashinfo.com 的页面模板并非完全统一早期年份和近年份的表格列数可能不同或者某些年份的表格嵌套了额外标签。解决不要假设所有年份结构一致。先写一个检查函数输出每年的列数和列名对比后再决定是统一重命名还是分组合并。如果差异太大可以考虑按年份分别保存分析时再按需合并。4.2 日期格式解析失败导致大量 NA现象mdy()或as.Date()之后date列出现大量 NA过滤后样本量骤减。原因原始日期字段可能包含“Jan 1, 2000”“1 January 2000”“2000-01-01”等多种格式单一解析函数无法覆盖。解决先用unique()看看日期字段有哪些模式再写一个分支解析函数。常见做法是用parse_date_time()指定多个候选格式或者用case_when()按模式分别处理。解析失败的行不要急着删先导出看看是不是格式特殊。4.3 死亡人数字段混入非数字字符现象as.numeric()转换后产生大量 NA并伴随警告“NAs introduced by coercion”。原因死亡人数字段可能包含“123 (123)”“约 100”“unknown”等非纯数字内容。解决先用str_extract()提取第一个连续数字再转数值。对于“unknown”这类可以统一替换为 NA 并在分析时排除。不要直接用as.numeric()硬转否则会丢失信息且难以排查。4.4 重复抓取导致同一条事故出现多次现象合并后的数据框里同一天同一地点的事故出现两到三次。原因可能是页面本身重复列出也可能是抓取时循环逻辑有误比如年份范围重叠或者 URL 拼接错误。解决用distinct()按关键字段去重同时检查年份循环是否有多余的重复。建议在抓取阶段就打印每年的记录数异常高的年份重点排查。4.5 在线抓取被限流或超时现象批量抓取时部分年份返回空表或报错重试后又正常。原因目标站点对频繁请求有限制或者本地网络不稳定。解决在循环里加Sys.sleep()控制请求频率一般 1 到 2 秒比较安全。用possibly()或tryCatch()包裹单次抓取失败时记录年份并跳过最后统一重试失败年份。不要一次性抓几十年分批次跑更稳妥。5. 进阶用法用 R 做事故趋势可视化与交互式查询5.1 快速绘制年度事故数与死亡人数趋势图清洗完的数据可以直接用ggplot2出图。下面这段代码展示了如何把年度事故数和平均死亡人数画在同一张图上双轴虽然不推荐但用于快速探索很方便。更常见的做法是分面或者用两条独立的时间序列。library(ggplot2) yearly_summary - normalized_data %% group_by(year) %% summarise( accidents n(), total_fatalities sum(fatalities_num, na.rm TRUE), avg_fatalities mean(fatalities_num, na.rm TRUE) ) ggplot(yearly_summary, aes(x year)) geom_line(aes(y accidents, color 事故数), size 1) geom_line(aes(y avg_fatalities, color 平均死亡人数), size 1) scale_color_manual(values c(事故数 steelblue, 平均死亡人数 firebrick)) labs( title 年度事故数与平均死亡人数趋势, x 年份, y 数值, color 指标 ) theme_minimal()这段代码先用group_by()和summarise()生成年度汇总表再用ggplot2画两条线。scale_color_manual()用来指定颜色映射避免默认配色难以区分。注意size参数在较新版本的ggplot2里被linewidth替代如果报错就换成linewidth。这张图适合快速看趋势如果要发表或做报告建议分开画或者用分面。5.2 用 DT 包做交互式事故查询表如果你想把数据分享给不写代码的同事可以用DT包生成一个可搜索、可排序的 HTML 表格。下面这段代码展示了如何把清洗后的数据渲染成交互表并限制默认显示行数。library(DT) datatable( normalized_data %% select(date, location_clean, operator_clean, aircraft, fatalities_num) %% arrange(desc(date)), filter top, options list( pageLength 15, autoWidth TRUE, scrollX TRUE ), caption 飞机失事历史记录清洗后 )filter top会在表格顶部加一排筛选框方便按地点或运营商过滤。pageLength 15控制默认每页显示行数避免一次性渲染太多行导致卡顿。scrollX TRUE在列数较多时启用横向滚动。这个表可以直接嵌入 R Markdown 文档导出 HTML 后发给别人用浏览器打开。5.3 一个我踩过的坑不要用原始数据直接做回归早期我图省事直接把抓下来的原始表扔进lm()做死亡人数和年份的回归结果系数完全不可解释。后来发现两个问题一是死亡人数字段里混了非数字被强制转换后产生大量 NA实际参与回归的样本只剩一小部分二是不同年份的事故记录完整度不一样早期年份漏记严重直接回归等于用有偏样本拟合。从那以后我每次拿到这类历史数据都强制走一遍“字段类型检查 → 缺失模式可视化 → 样本完整性评估”三步确认数据质量后再建模。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取

相关新闻

高德地图校园导航Android项目实战:从Key配置到路线规划全解析

高德地图校园导航Android项目实战:从Key配置到路线规划全解析

简介:这份基于高德地图的校园导航资源,是面向在校学生与初学者的完整项目包,适用于课程设计、毕业设计或项目初期演示。包内提供可直接运行的Android工程与APK安装包,涵盖Java源码、XML布局与配置、Gradle构建脚本及多个SO库&…

2026/10/13 11:46:22 阅读更多 →
时间卷积网络TCN时序预测实战:从零用PyTorch跑通并避坑

时间卷积网络TCN时序预测实战:从零用PyTorch跑通并避坑

简介:这份资源面向初级及以上水平的数据科学家、机器学习爱好者,以及希望深入掌握时间序列预测落地方法的从业者,核心是用Python与TensorFlow搭建时间卷积神经网络(TCN),解决未来数值走向预测问题&#xff…

2026/10/13 11:46:22 阅读更多 →
递归下降分析实战:从文法改造到语法树构建与表达式求值

递归下降分析实战:从文法改造到语法树构建与表达式求值

简介:这份编译原理实验资料面向计算机专业学生及编译器初学者,聚焦自上而下语法分析中的递归下降分析法,帮助读者掌握从文法改造到程序实现的完整流程。资源包内含1个doc文档,约80KB,以实验报告形式呈现,涵…

2026/10/13 11:46:22 阅读更多 →

最新新闻

智能体上下文超限被强制截断引发的错答事故排障

智能体上下文超限被强制截断引发的错答事故排障

在刚刚过去的双 11 核心大促零点峰值期间,某头部电商平台的核心智能客服与导购智能体(AI Shopping Agent)突发了一起极其严重的线上 P1 级业务资损事故:海量涌入的用户在多轮互动咨询过程中,智能体针对多款高价值 3C 数…

2026/10/13 12:32:32 阅读更多 →
Ubuntu 16.04下Miniconda环境隔离与科学计算复现实战

Ubuntu 16.04下Miniconda环境隔离与科学计算复现实战

1. 项目概述:为什么在Ubuntu 16.04上认真对待Anaconda安装这件事你点开这篇内容,大概率不是为了“随便装个Python环境”,而是正卡在某个具体场景里:可能是刚接手一台实验室老服务器,系统被锁死在Ubuntu 16.04 LTS&…

2026/10/13 12:32:32 阅读更多 →
brick-design 的 BrickTree 组件深度解析:与画布实时同步的组件树、拖拽排序与页面结构编辑

brick-design 的 BrickTree 组件深度解析:与画布实时同步的组件树、拖拽排序与页面结构编辑

低代码前端 【免费下载链接】brick-design 低代码框架,支持流式布局与自由布局拖拽编排,可视化拖拽、随意嵌套组合、实时渲染、实时辅助线展示、自由布局支持辅助对齐、支持自动吸附、实时组件间距展示、实时拖拽排序、状态域管理,可视化属性…

2026/10/13 12:32:32 阅读更多 →
毕业设计管理系统实战:SpringBoot+Vue+MyBatis+MySQL全栈开发

毕业设计管理系统实战:SpringBoot+Vue+MyBatis+MySQL全栈开发

每年到了毕业季,做毕设管理系统的需求就特别多。有的是老师要处理几十个学生的选题、开题、中期检查、答辩评分,用Excel来回传文件简直能让人崩溃;有的则是学生要做毕设,想找一个结构完整、能出成果的技术项目作为参考。我去年帮某…

2026/10/13 12:32:32 阅读更多 →
从1980到2018:全国30米土地利用型数据与长时序应用指南

从1980到2018:全国30米土地利用型数据与长时序应用指南

说实话,我在这行干了这么多年,带过不少做土地利用变化分析的新人。每次他们跑过来问我"想研究长时间序列的土地利用变化,但不知道用什么数据",我第一个想到的就是这类长时序中分辨率土地利用数据集。这次要聊的"19…

2026/10/13 12:32:32 阅读更多 →
openGauss数据库实验指南:从环境搭建到JDBC连接全解析

openGauss数据库实验指南:从环境搭建到JDBC连接全解析

简介:一份完整的《zzu数据库实验报告书》,面向计算机科学与技术、软件工程专业正在学习《数据库系统原理》课程的学生,覆盖认识DBMS、创建数据库/表/索引、交互式SQL语句、视图、完整性控制、安全性控制、事务与并发控制、数据库备份与恢复、…

2026/10/13 12:31:31 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 18:11:17 阅读更多 →