开发者百宝箱:使用Bash清理数据

译者 | 布加迪

审校 | 重楼

你是否已厌倦了使用臃肿的工具来处理杂乱的数据?本文介绍了如何使用Bash 清理和转换数据集。

今天,我们将学习如何使用Bash清理数据,这是处理数据的任何人必备的一项技能。虽然我们许多人在处理数据时会使用PythonR,但也可以使用Bash快速高效地处理数据,可直接从命令行进行处理

本文不仅会介绍相关命令,还逐步介绍了每个步骤背后的思考过程,解释我们为什么使用特定命令以及它们如何协同工作解决常见的数据清理问题。

让我们开始吧

了解数据清理过程

在深入探讨代码之前,不妨先了解一下数据清理的实际含义。数据清理指将杂乱的原始数据转化准确、完整、随时可供分析的数据。这包括:

处理缺失值修复格式问题删除重复数据标准化不一致的数据依据业务规则验证数据

因此,干净的数据对于准确的分析和可靠的结果至关重要。垃圾进垃圾出”这个原则非常适用于数据科学(这并不奇怪)。

我们在本教程中将使用一个示例数据集users.csv 文件

了解的数据

在进行任何更改之前,了解在处理的数据很重要。不妨探究一些基本的检查命令。

要查看文件的内容,可以使用cat 命令。

复制
$ cat users.csv1.

输出:

复制
1,John,Smith,john.smith@example.com,2023-01-15,2023-03-20,125.99 2,Jane,Doe,jane.doe@example.com,2023-01-16,2023-03-21,210.50 3,Bob,Johnson,bob@example.com,2023-01-17,2023-03-22,0 4,Alice,Williams,alice.williams@example.com,2023-01-18,,75.25 5,,Brown,mike.brown@example.com,2023-01-19,2023-03-24,150.75 6,Sarah,Miller,sarah.miller@example.com,invalid_date,2023-03-25,95.00 7,David,Jones,david.jones@example.com,2023-01-21,2023-03-26,300.00 8,Lisa,Garcia,lisa.garcia@example.com,2023-01-22,2023-03-27,-50.00 9,James,Martinez,mymail@example.com,2023-01-23,2023-03-28,125.001.2.3.4.5.6.7.8.9.

对于大型文件,这可能不切实际,于是我们有其他选择。

head 命令默认显示文件的前10 行。这对于快速检查数据的结构和标题非常有用。

复制
$ head users.csv1.

可以使用-n选项指定不同的行数。

复制
$ head -n 5 users.csv1.

结果如下:

复制
id,first_name,last_name,email,signup_date,last_login,purchase_amount 1,John,Smith,john.smith@example.com,2023-01-15,2023-03-20,125.99 2,Jane,Doe,jane.doe@example.com,2023-01-16,2023-03-21,210.50 3,Bob,Johnson,bob@example.com,2023-01-17,2023-03-22,0 4,Alice,Williams,alice.williams@example.com,2023-01-18,,75.251.2.3.4.5.

同样,tail默认显示文件的最后10行。这有助于检查日志文件或时间序列数据中的最新条目。

带有-l标志的wc(字数统计)命令可以统计文件中的行数。这可以让快速了解数据集的大小。

复制
$ wc -l users.csv1.

输出结果:

复制
11 users.csv1.

可以使用以下命令查看文件结构:

复制
$ column -t -s, users.csv | less -S1.

命令对于CSV文件尤其有用。下面不妨细述一下:

column 将输出格式化为列-t 指示它创建表格-s 指定逗号为分隔符less -S允许滚动浏览输出而不换行

这为提供了格式良好的数据视图,从而容易发现不一致的地方

查找和分析数据中的问题

我们对数据有了一番基本的了解,不妨识别具体的问题。

命令使用grep搜索连续的逗号(表示空字段),并使用-c来计数出现的次数。

复制
$ grep -c ",," users.csv1.

这为我们提供了一种快速统计缺失值行的方法。

复制
21.

grep添加-n 标志可以显示行号以及匹配项帮助我们精确定位缺失值的位置。

复制
$ grep -n ",," users.csv1.

输出:

复制
5:4,Alice,Williams,alice.williams@example.com,2023-01-18,,75.25 6:5,,Brown,mike.brown@example.com,2023-01-19,2023-03-24,150.751.2.

以下命令识别日期格式无效的行,具体来说在示例数据中查找文本invalid_date

复制
$ grep -v -E ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ users.csv | grep "invalid_date"1.

输出:

复制
6,Sarah,Miller,sarah.miller@example.com,invalid_date,2023-03-25,95.001.

不妨查找购买金额为负数的记录:

复制
$ awk -F, $7 < 0 {print $0} users.csv1.

awk 命令可以

使用-F指定逗号为字段分隔符检查第7个字段purchase_amount是否小于 0如果条件成立,打印输出整行

输出:

复制
8,Lisa,Garcia,lisa.garcia@example.com,2023-01-22,2023-03-27,-50.001.

使用数据清理技术解决问题

我们已确定了问题所在,现在不妨逐一解决

处理缺失值

首先,我们将空字段替换为NULL

复制
$ sed s/,,/,NULL,/g; s/,$/,NULL/g users.csv > users_cleaned.csv1.

sed 命令:

将连续的逗号,,替换为,NULL,,使缺失值显式显示使用s/,$/,NULL/g 处理行尾的尾随逗号将结果写入名为users_cleaned.csv 的新文件

> 运算符将输出重定向到新文件而不是屏幕。

我们可以用Unknown填充缺失的名字。

复制
$ awk -F, BEGIN {OFS=","} {if ($2 == "") $2 = "Unknown"; print} users.csv > users_cleaned.csv1.

awk 命令可以

使用-F将输入字段分隔符设置为逗号使用BEGIN {OFS=","} 将输出字段分隔符也设置为逗号检查第二个字段first_name是否为空将空值替换为Unknown”。打印输出每一行(无论是否修改)更正日期格式

sed 命令将文本“invalid_date替换为格式正确的日期。

复制
$ sed s/invalid_date/2023-01-20/g users.csv > users_cleaned.csv1.

实际上,可能需要使用上下文中适用的日期,或者标记这些条目供进一步查看

处理负值

可以将负值替换为零。

复制
$ awk -F, BEGIN {OFS=","} {if ($7 < 0) $7 = 0; print} users.csv > users_cleaned.csv1.

命令可以

检查第七个字段purchase_amount是否小于 0将负值设置为 0如果原始值不是负数,则保留原始值。

组合多个数据清理步骤

实际上常需要对数据进行多重处理。以下是将它们组合成单个命令的方法:$ awk -F, BEGIN {OFS=","} {

复制
# Fix missing first names if ($2 == "") $2 = "Unknown"; # Fix invalid dates if ($5 == "invalid_date" || $5 == "") $5 = "2023-01-20"; if ($6 == "") $6 = "2023-03-23"; # Fix negative values if ($7 < 0) $7 = 0; print } users.csv > users_cleaned.csv1.2.3.4.5.6.7.8.9.10.11.12.

命令的工作原理如下:

根据每个字段的特定验证规则处理它们在一次数据传递中处理多个问题

这种方法比为每个问题运行单独的命令来得更高效,尤其对于大型数据集而言。

验证数据清理步骤

清理数据后,务必验证所有问题是否已解决。

检查是否没有空字段:

复制
$ grep -c ",," users_cleaned.csv1.

如果所有空字段都已正确填写,则返回 0。

接下来,确保所有日期格式正确:

复制
$ grep -v -E [0-9]{4}-[0-9]{2}-[0-9]{2} users_cleaned.csv | grep -v "signup_date"1.

如果所有日期格式正确,则返回结果为空

检查所有购买金额是否为非负数:

复制
$ awk -F, $7 < 0 {print $0} users_cleaned.csv1.

如果所有购买金额都为非负数,则返回结果为空。

转换数据

数据清理完成后,可能需要将某些字段转换不同的格式,或提取特定信息进行分析。

提取特定列

不妨仅提取姓名和邮箱地址(联系信息):

复制
$ cut -d, -f2,3,4 users_cleaned.csv > users_contact_info.csv1.

cut命令:

使用-d,指定逗号为分隔符使用-f2,3,4 提取第 234个字段(first_name、last_name、email)创建一个仅包含这些列的新文件

只需要特定信息进行特定分析时,这非常有用。

接下来,我们尝试提取购买金额超过100 美元的用户。

复制
$ awk -F, $7 > 100 {print $0} users_cleaned.csv > users_high_value.csv1.

awk命令根据条件过滤行,创建符合特定条件的数据子集。

数据排序

我们跳过标题行,按姓氏对记录进行排序。

复制
$ (head -n 1 users_cleaned.csv && tail -n +2 users_cleaned.csv | sort -t, -k3) > users_sorted_by_name.csv1.

命令:

使用head -n 1 保留标题行使用tail -n +2 获取除标题之外的所有行使用sort -t, -k3 按第三个字段(last_name)对数据进行排序将标题和排序后的数据合并到一个新文件中

#按购买金额降序排序

复制
(head -n 1 users_cleaned.csv && tail -n +2 users_cleaned.csv | sort -t, -k7 -n -r) > users_sorted_by_purchase.csv1.

命令按购买金额降序排序数据:

-t,指定逗号为分隔符-k7 按第七个字段(purchase_amount)排序-n 确保按数字排序(非字母顺序)-r 按反向(降序)排序

聚合和分析数据

Bash也可用于基本数据分析。不妨计算一下总购买金额

复制
$ awk -F, NR>1 {sum += $7} END {print "Total purchases: $" sum} users_cleaned.csv1.

awk 命令:

跳过NR>1 的标题行将第7个字段purchase_amount中的所有值相加在末尾打印输出购买金额。
复制
Total purchases: $1282.491.

现在不妨计算一下平均购买金额:

复制
$ awk -F, NR>1 {sum += $7; count++} END {print "Average purchase: $" sum/count} users_cleaned.csv1.

命令以下方式计算平均值:

将所有购买金额相加计算记录数总购买金额除以末尾的计数
复制
Average purchase: $128.2491.

接下来,不妨按注册月份统计用户数量:

复制
$ awk -F, NR>1 { split($5, date, "-"); months[date[2]]++; } END { for (month in months) { print "Month " month ": " months[month] " users" } } users_cleaned.csv1.2.3.4.5.6.7.8.9.

这个更复杂的awk 命令可以

从注册日期中提取月份使用关联数组months统计出现次数按月份打印输出用户摘要
复制
Month 01: 10 users1.

创建用于清理数据的 Bash 脚本

创建可重用的Bash脚本以清理数据通常很方便。具体操作方法如下:

将数据清理命令保存到文件中,比如clean_user_data.sh(该脚本包含几个额外的数据清理步骤)使用chmod +x clean_user_data.sh 使其可执行使用./clean_user_data.sh 运行该脚本

clean_user_data.sh 脚本:

分别处理每个清理步骤,但将所有更改写入同一个输出文件包含进度消息以跟踪执行情况清理后执行验证检查轻松修改以添加更多清理步骤或更改现有清理步骤如果存在临时文件,末尾删除临时文件

逐个运行命令和运行脚本都可以实现相同的目标,但脚本便于清楚地了解清理过程,并简化故障排除。

结语

但愿本教程能为使用Bash清理数据提供了坚实的基础。

关键要点:

Bash非常适合快速高效地清理中小型数据集。grep、awk、sed 和sort 等命令的组合提供了一套灵活的工具包。可以使用Bash 脚本清理数据以及清理过程记入文档

请记住,虽然Bash功能强大,但它只是数据工具箱中的一种工具。对于非常大的数据集或更复杂的转换,可能需要考虑使用Python、R或专用的ETL工具。然而对于许多日常数据清理任务而言,Bash 的效率和效果都出奇地好!

祝清理愉快!

原文标题:Data Cleaning with Bash: A Handbook for Developers作者:Bala Priya C

THE END
本站服务器由亿华云赞助提供-企业级高防云服务器