做导师一般去什么网站找素材帮人做兼职的网站
做导师一般去什么网站找素材,帮人做兼职的网站,国内做化妆刷的比较好的网站,手机百度最新正版下载R语言数据清理神器janitor包#xff1a;5分钟搞定Excel导入的脏数据问题
你是否也曾面对从Excel导入R的数据框感到头疼#xff1f;那些带着空格和特殊符号的列名、混杂着数字和文本的日期列、隐藏在角落里的空行空列#xff0c;还有那些因为合并单元格而产生的重复表头…R语言数据清理神器janitor包5分钟搞定Excel导入的脏数据问题你是否也曾面对从Excel导入R的数据框感到头疼那些带着空格和特殊符号的列名、混杂着数字和文本的日期列、隐藏在角落里的空行空列还有那些因为合并单元格而产生的重复表头每一次手动清理都像是在数据泥潭里挣扎。对于从Excel或SPSS转向R的数据分析师来说数据导入后的“第一公里”清理工作往往消耗了本应用于核心分析的时间和精力。今天我想和你分享一个我在日常工作中离不开的R包——janitor。它不是什么复杂的高深工具却实实在在地解决了我90%的数据清洗痛点。特别是当你需要快速处理来自业务部门、合作伙伴或公开数据源的Excel文件时janitor提供的那几个简洁函数能让你在几分钟内将杂乱的数据整理得干干净净直接进入分析环节。这篇文章不是简单的函数罗列而是基于我处理过上百个“脏”Excel文件的实战经验为你梳理出一套高效、可复用的janitor工作流。1. 认识janitor专为“脏数据”而生的清洁工janitor包的哲学非常直接数据科学家不应该把时间浪费在重复、琐碎的清理任务上。它的作者Sam Firke在设计这个包时瞄准的就是那些从Excel、CSV甚至网页表格导入R后出现的各种“不整洁”数据。与tidyverse生态完美融合特别是与管道操作符%%的协同让数据清洗流程变得异常流畅。1.1 janitor解决的核心痛点在我接触过的数据项目中Excel导入的“脏数据”通常有以下几个典型特征列名灾难包含空格如Employee Name、特殊字符如% Allocated、大小写混用甚至直接就是Excel的默认列名如...2,X__1。结构冗余数据区域外存在多余的表头行、汇总行或者因合并单元格产生的完全空白的行和列。格式混乱同一列中混合了多种数据类型比如日期列里既有“2023-01-15”这样的文本也有Excel序列号44927。值不一致分类变量中的值存在大小写、空格或同义不同词的差异例如“Yes”、“YES”、“Y”并存。janitor并没有试图创造一个无所不包的巨型清洗框架而是精准地提供了针对上述问题的“手术刀式”函数。它的核心优势在于专注和管道友好。你不需要为了清理列名去写复杂的正则表达式也不需要为了删除空行而写循环判断。1.2 安装与初体验安装janitor非常简单直接从CRAN获取即可# 从CRAN安装稳定版 install.packages(janitor) # 或者如果你想体验最新的开发版功能通常不必要 # install.packages(devtools) # devtools::install_github(sfirke/janitor)安装后加载它并准备一个典型的脏数据场景。假设我们有一个名为dirty_employee_data.xlsx的Excel文件它的结构可能比我们想象的还要糟糕Data refreshed on: 2023-10-27...2...3...4First NameLast NameHire Date% AllocatedJohnDoe445621.0JaneSmith2019-07-150.75Subtotal这个表格包含了多余的表头行、混合格式的日期、带百分号的列名以及无用的汇总行。用readxl::read_excel()读入后你会得到一个需要大量预处理的数据框。而janitor的目标就是让你用最少的代码解决这些问题。2. 核心清洗函数实战从混乱到整洁janitor的清洗流程可以概括为一个清晰的链条先处理结构列名、空行空列再处理内容数据类型、重复值。让我们结合一个更复杂的模拟数据集一步步拆解。2.1 第一步驯服列名 -clean_names()与make_clean_names()列名是数据框的“门面”也是后续所有dplyr操作如select(),mutate()的基础。混乱的列名会让代码可读性急剧下降。clean_names()是janitor最著名的函数它默认执行以下转换将所有字符转为小写。将空格和特殊字符如%,(,),$替换为下划线_。处理重复的列名为其添加后缀。确保列名符合R的语法要求尽管不是强制必须的但能避免很多意外错误。library(readxl) library(janitor) library(dplyr) # 模拟读取一个列名混乱的数据 messy_df - tibble( First Name c(Alice, Bob), Last Name c(Smith, Jones), Hire Date (MM/DD/YYYY) c(44562, 2020-01-01), % Allocated c(1.0, 0.5), Full Time? c(Y, N) ) print(messy_df) # # A tibble: 2 × 5 # First Name Last Name Hire Date (MM/DD/YYYY) % Allocated Full Time? # chr chr chr dbl chr # 1 Alice Smith 44562 1 Y # 2 Bob Jones 2020-01-01 0.5 N # 使用clean_names()一键清理 clean_df - messy_df %% clean_names() print(clean_df) # # A tibble: 2 × 5 # first_name last_name hire_date_mm_dd_yyyy percent_allocated full_time # chr chr chr dbl chr # 1 Alice Smith 44562 1 Y # 2 Bob Jones 2020-01-01 0.5 N提示clean_names()提供了多种命名风格选项如snake默认小写下划线、lower_camel、upper_camel等可以通过case参数指定。例如clean_names(case lower_camel)会得到firstName这样的列名。有时你希望在数据读取阶段就进行列名清理readxl和readr等包支持.name_repair参数。这时可以使用make_clean_names()函数它作用于字符向量返回清理后的字符向量。# 在读取Excel时直接应用列名清理 clean_df_from_source - read_excel(dirty_data.xlsx, .name_repair make_clean_names)2.2 第二步剔除无效结构 -remove_empty()与remove_constant()数据中无意义的空行、空列以及所有值都相同的常数列会干扰分析和建模。remove_empty()和remove_constant()就是用来清除这些“噪音”的。# 创建一个包含空行、空列和常数列的数据框 df_with_junk - tibble( id c(1, 2, NA, 4), name c(A, B, NA, D), empty_col c(NA, NA, NA, NA), # 全为空值的列 constant_col c(Yes, Yes, Yes, Yes), # 常数列 another_empty rep(NA, 4) ) # 假设第三行全是NA空行 # 移除所有完全为空的行和列 df_cleaned - df_with_junk %% remove_empty(which c(rows, cols)) print(df_cleaned) # 此时empty_col和another_empty列以及第三行空行已被移除。 # 进一步移除常数列 df_further_cleaned - df_cleaned %% remove_constant() print(df_further_cleaned) # constant_col列值全为Yes也被移除了。remove_constant()的na.rm参数非常有用。当设置为TRUE时它会忽略NA值。这意味着如果一列除了NA之外的所有非NA值都相同该列也会被视为常数列而被移除。2.3 第三步处理混合格式日期 -convert_to_date()从Excel导入的日期可能是R最头疼的问题之一。Excel内部以序列号存储日期而用户可能以文本形式输入。导致一列中同时存在数字如44927和字符串如2023-01-15。手动处理需要判断类型、分别转换极其繁琐。convert_to_date()函数智能地解决了这个问题。它会尝试解析输入的每个元素无论是数字、字符串还是因子并将其统一转换为R的Date类型。# 继续使用之前的clean_dfhire_date_mm_dd_yyyy列是字符型但包含Excel序列号和字符串 clean_df - clean_df %% mutate(hire_date convert_to_date(hire_date_mm_dd_yyyy)) print(clean_df$hire_date) # [1] 2022-01-01 2020-01-01 # 44562被正确转换为2022-01-01这个函数底层使用了lubridate包的解析器支持多种日期格式。如果你的日期格式比较特殊还可以通过character_fun参数指定自定义的解析函数。3. 高级清理与质量检查基础清理完成后数据可能还存在一些更深层次的问题比如重复的记录或者需要快速进行探索性分析。janitor也为此提供了得力的工具。3.1 精准定位重复记录 -get_dupes()重复数据是影响分析结果的常见问题。dplyr的distinct()可以删除重复项但有时我们需要先查看重复项以判断是数据错误还是合理情况比如同一个客户多次交易。get_dupes()可以快速找出并标记重复行。# 创建一个有重复记录的数据 duplicate_data - tibble( employee_id c(101, 102, 101, 103, 102), name c(John, Jane, John, Alice, Jane), department c(Sales, Tech, Sales, HR, Tech) ) # 找出基于employee_id和name的重复记录 dupes_found - duplicate_data %% get_dupes(employee_id, name) print(dupes_found) # # A tibble: 4 × 4 # employee_id name dupe_count department # dbl chr int chr # 1 101 John 2 Sales # 2 101 John 2 Sales # 3 102 Jane 2 Tech # 4 102 Jane 2 Tech输出结果中会多出一列dupe_count显示该重复组合出现了多少次。这比单纯用group_by和filter(n()1)更直观因为它保留了所有重复行的原始数据方便你检查每一行。3.2 探索性制表与美化 -tabyl()与adorn_*()系列在数据清洗和报告阶段我们经常需要快速计算频率表。R自带的table()函数功能有限且输出结果不易进一步处理。janitor的tabyl()函数产生了类似dplyr::count()的tibble但功能更强大并且与adorn_*()装饰函数链式结合后能直接生成可用于报告的精美汇总表。tabyl()的基本用法非常直观# 使用之前清理好的roster数据示例 # 单变量频数表自动计算计数、百分比和有效百分比 roster %% tabyl(employee_status) # 输出为数据框包含n, percent, valid_percent列 # 双变量交叉表 status_vs_time - roster %% tabyl(employee_status, full_time) print(status_vs_time) # employee_status No Yes # Administration 0 1 # Coach 2 0 # Teacher 3 4tabyl()的输出本身已经很有用但adorn_*()函数能让它变得“好看”且“信息丰富”。这些函数是模块化的可以按需组合。# 一个完整的装饰链条添加总计、计算行百分比、格式化并添加标题 presentation_table - roster %% tabyl(employee_status, full_time) %% adorn_totals(where row) %% # 添加行总计 adorn_percentages(denominator row) %% # 计算行百分比 adorn_pct_formatting(digits 1) %% # 将百分比格式化为带%的字符串 adorn_ns(position front) %% # 在百分比前显示原始计数格式为“计数 (百分比)” adorn_title(placement combined) # 将行列标题合并 print(presentation_table) # employee_status/full_time No Yes # Administration 0.0% (0) 100.0% (1) # Coach 100.0% (2) 0.0% (0) # Teacher 33.3% (3) 66.7% (6) # Total 41.7% (5) 58.3% (7)这个装饰好的数据框可以直接通过knitr::kable()输出到R Markdown或Quarto文档中生成专业的表格。这套组合拳极大地简化了从数据到可发布汇总表的流程。4. 构建5分钟高效清洗流水线了解了各个工具后关键在于如何将它们串联成一个高效、稳健的流水线。下面我结合一个真实的复杂案例展示如何用janitor在管道中一气呵成。假设我们收到一个名为financial_report_Q3.xlsx的文件它存在以下问题前两行是合并单元格的表头和副标题。列名包含空格和单位如Revenue ($)。最后一行是“总计”行。有一列Notes几乎全为空。Date列混合了“DD/MM/YYYY”和Excel序列号。我们的清洗目标是在一个管道内完成读取、清理、类型转换得到一个可直接分析的数据框。library(readxl) library(janitor) library(dplyr) library(lubridate) cleaned_financial_data - read_excel(financial_report_Q3.xlsx, skip 2, # 跳过前两行非数据行 .name_repair make_clean_names # 读入时初步清理列名 ) %% # 第一步使用janitor核心清理 clean_names(case snake) %% # 确保列名风格统一 remove_empty(which c(rows, cols)) %% # 删除空行空列 remove_constant(na.rm TRUE) %% # 删除所有值相同的列如全为“N/A”的Notes列 # 第二步使用dplyr进行数据转换 filter(!str_detect(region, (?i)total|summary)) %% # 删除包含“总计”、“汇总”的行正则表达式 mutate( across(where(is.character), ~na_if(., N/A)), # 将字符型列中的N/A替换为NA date convert_to_date(date, character_fun dmy), # 处理混合格式日期假设原格式为日/月/年 revenue_usd parse_number(revenue) # 如果revenue列是带千位符或货币符号的字符串转换为数字 ) %% # 第三步最后的质量检查可选但推荐 get_dupes(region, date) # 检查是否有同一地区同一日期的重复记录结果可以另存检查 # 查看最终数据结构 glimpse(cleaned_financial_data)这个管道可能看起来步骤不少但一旦写成脚本对于任何结构类似的脏Excel文件你只需要修改文件名和skip参数就能在5分钟内得到整洁数据。关键在于将janitor的自动化清理与dplyr的精确数据操作结合起来。在实际项目中我习惯将这样的清洗流程封装成一个自定义函数比如clean_excel_data()将文件路径和少数几个参数如跳过的行数、日期格式作为输入返回整洁的数据框。这样团队中的其他成员即使不熟悉janitor的所有细节也能通过调用这个函数快速完成数据预处理把更多精力投入到有价值的业务分析中去。janitor的价值正在于它将那些繁琐、易错的操作标准化、自动化让数据工作的起点变得更加清爽和高效。