Python数据可视化

当有人提到“清理数据”时,首先浮现在脑海中的往往是打开一个 Jupyter Notebook,开始使用 pandas 进行操作。但有一点很少有人记得:这项清理工作中有一部分非常强大的功能可以直接在终端中完成,利用系统中已经安装的工具。

在这里,你将看到如何使用基本的命令行工具来清理、转换和探索数据文件。不需要安装一堆东西:只需打开你的终端,并在文件夹中放置一些 CSV 文件,就像你在处理一个充满客户注册问题的电子表格一样。

在开始输入命令之前,了解一下这在日常工作中为何如此有用:

  • 命令行工具简单易用,快速高效,尤其是在处理大型文件时,比如系统日志、巨型 CSV 摘要或 ERP 导出。
  • 它们在 Linux 和 macOS 中自带,也有 Windows 版本。
  • 在将所有数据加载到 Python 或其他语言之前,它们非常适合用来初步查看数据。
  • 可以轻松将命令串联在脚本中,并将这套清理流程作为自动化的一部分重复使用,无论是在定时任务、数据管道还是维护脚本中。

让我们开始动手吧。

提示:想象一下,这段文字旁边有一个在GitHub上的Bash脚本。我们的想法是让你打开终端,把文件放在一旁,逐行复制命令,以便亲身体验它是如何工作的。


创建一个“脏”数据集

第一步:构建一个非常混乱的CSV文件来进行练习。它模拟了在HR登记、销售表格、学生名单等实际问题中出现的情况。

cat > messy_data.csv << 'EOF'
name,age,salary,department,email
John Lee,32,50000,Engineering,john@example.com
Jane Smith,28,55000,Marketing,jane@example.com
   Bob Davis    ,35,60000,Engineering,bob@example.com
Alice Williams,29,,Marketing,alice@example.com
Charlie Brown,45,70000,Sales,charlie@example.com
Dave Wilson,31,52000,Engineering,
Emma Davis,,58000,Marketing,emma@example.com
Frank Miller,38,65000,Sales,frank@example.com
John Lee,32,50000,Engineering,john@example.com
Grace Lee,27,51000,Engineering,grace@example.com
EOF

这个迷你数据集已经存在多个典型问题:一些名称前后有多余的空格、缺失的值、重复的行。这种情况通常出现在你合并来自不同系统的数据、导入多个人的电子表格或从不同平台下载报告时。这是一个很好的学习场景。


1. 使用 headtailwc 探索您的数据

在尝试修复任何内容之前,您需要了解自己正在处理的内容。这就像打开一个杂乱的橱柜,先看一眼,然后决定什么要扔掉,什么要捐赠,什么要放回架子上。

# 查看前5行(包括标题)
head -n 5 messy_data.csv

# 查看最后3行
tail -n 3 messy_data.csv

# 统计总行数(包括标题)
wc -l messy_data.csv

这里发生了什么?

  • head -n 5 显示前5行,这是一个快速预览,用于查看文件格式是否符合预期。
  • tail -n 3 显示最后3行,非常适合检查文件是否正确结束,或者最后是否有行被截断。
  • wc -l 统计行数;减去1(标题行),你就可以知道实际有多少条记录。

示例输出:

name,age,salary,department,email
John Lee,32,50000,Engineering,john@example.com
Jane Smith,28,55000,Marketing,jane@example.com
   Bob Davis    ,35,60000,Engineering,bob@example.com
Alice Williams,29,,Marketing,alice@example.com
Frank Miller,38,65000,Sales,frank@example.com
John Lee,32,50000,Engineering,john@example.com
Grace Lee,27,51000,Engineering,grace@example.com
11 messy_data.csv

这就像在LibreOffice中快速查看一个电子表格,只是想确认数据“看起来”是否正确。


2. 使用 cut 查看特定列

并不总是想查看整个文件。有时,只想知道人名和他们工作的部门,比如当你的老板说“只给我发一份包含姓名和部门的列表,其他的无所谓”。

cut -d',' -f1,4 messy_data.csv

逐步理解:

  • cut 是一个用于“剪切”每行部分内容的工具。
  • -d',' 指定字段的分隔符;这里是逗号,和任何标准的CSV一样。
  • -f1,4 表示你想要第1列和第4列(姓名和部门)。

你还可以使用列的范围:-f1-3 会获取从第1列到第3列的内容。

输出:

name,department
John Lee,Engineering
Jane Smith,Marketing
   Bob Davis    ,Engineering
Alice Williams,Marketing
Charlie Brown,Sales
Dave Wilson,Engineering
Emma Davis,Marketing
Frank Miller,Sales
John Lee,Engineering
Grace Lee,Engineering

这很像在电子表格中筛选列,只不过在这里你可以用一行命令来实现,并且可以将其嵌入到可重用的脚本中。


3. 使用 sortuniq 移除重复行

注意到“John Lee”在文件中出现了两次吗?在真实的数据库中,这种情况很常见:客户重复注册、学生重复、员工在工资单中出现两次。

我们来处理一下这个问题。

# 首先保存表头
head -n 1 messy_data.csv > cleaned_data.csv

# 移除其余部分的重复项(不包括表头)
tail -n +2 messy_data.csv | sort | uniq >> cleaned_data.csv

每个部分的作用是什么?

    • head -n 1 只获取第一行,即表头,并保存到 cleaned_data.csv 中。
    • tail -n +2 从第二行开始获取所有内容,跳过表头。
    • sort 对行进行排序;这很重要,因为 uniq 只能删除相邻的重复项。
    • uniq 删除相邻的重复行。
    • >> 将结果追加到文件末尾(而不是像 > 那样覆盖)。

这就像拿一份点名单,按名字排序并划掉重复的,保持一切整齐有序。


4. 使用 grep 进行搜索和过滤

现在我们来谈谈搜索和过滤。想要只找到工程部门的人吗?或者找到空字段的行?解决这个问题的工具就是 grep,它可以直接在终端中使用。

# 查找所有包含“工程”的行
grep "Engineering" messy_data.csv

# 查找包含空字段的行(连续两个逗号)
grep ",," messy_data.csv

# 排除缺失数据的行
grep -v ",," messy_data.csv > no_missing.csv

工作原理:

  • grep "模式" 用于查找包含该文本的行。

grep -v 的作用是相反的:只显示符合模式的行。

  • ",,"的情况下,我们假设缺失的值变成了两个连续的逗号,这在CSV文件中某个字段为空时是很常见的。

 

这在你想要分离出一份“干净”的客户列表(所有字段都已填写)和一份只包含有问题记录的列表(以便后续修正)时,非常有用。


5. 使用sed去除多余空格

注意“Bob Davis”的记录:名字前后有多余的空格。这在比较、分组或在报告中美观地展示名字时会造成困扰。

我们来去掉这些多余的空格。

sed 's/^[ \t]*//; s/[ \t]*$//' messy_data.csv > trimmed_data.csv

这里发生了什么?

  • sed 是一个“流编辑器”,用于在文本通过命令时进行编辑,而无需打开图形编辑器。
  • s/模式/替换/ 是替换的语法。
  • ^[ \t]* 匹配行开头的空格或制表符。
  • [ \t]*$ 匹配行结尾的空格或制表符。
  • 分号分隔了两个操作:首先清理开头,然后清理结尾。

在实际操作中,这就像在电子表格中使用“删除多余空格”,只不过是在任何经过您管道的文本文件中。


6. 使用 sed 替换值

有时您需要标准化术语或纠正打字错误。想象一下,如果“Engineering”部门在内部报告中需要显示为“Tech”。

# 将所有出现的 "Engineering" 替换为 "Tech"
sed 's/Engineering/Tech/g' messy_data.csv

现在,假设您想用一个默认值填充空白电子邮件,例如 “no-email@example.com”,以确保没有任何行的该字段为空。

# 将空白电子邮件替换为 "no-email@example.com"
sed 's/,$/,no-email@example.com/' messy_data.csv

理解命令:

  • g 结尾表示“全局”:替换行中的所有出现,而不仅仅是第一个。
  • ,$ 表示行末的逗号,表明最后一个字段是空的。
  • 您可以使用 ; 在多个替换之间进行连接。

这就像在文本编辑器中进行“查找和替换”,但它的优势在于可以在脚本中运行,并在每次新文件到达时自动进行修正。


7. 使用 awk 进行计数和汇总

在处理字段、求和和简单统计时,awk 就像一把瑞士军刀。我们将用它来分析一下我们的文件。

# 按部门统计记录
tail -n +2 messy_data.csv | cut -d',' -f4 | sort | uniq -c

# 计算平均年龄(忽略表头和空值)
tail -n +2 messy_data.csv | awk -F',' '{if($2) sum+=$2; if($2) count++} END {print "平均年龄:", sum/count}'

这个 awk 做了什么?

  • -F',' 将逗号定义为字段分隔符。
  • $2 是第二个字段,我们的年龄列。
  • if($2) 确保我们只考虑年龄不为空的行。
  • sum += $2 会累加年龄。
  • count++ 计算进入计算的有效记录数量。
  • END { ... } 在遍历所有行后执行并打印平均值。

典型输出:

      5 工程部
      3 市场部
      2 销售部
平均年龄: 33

这就像是在要求 Excel 制作一个数据透视表和计算平均值,只不过一切都是在命令行中完成的。当你在没有图形界面的服务器上或者在设置自动化任务时,这非常有用。


8. 使用管道组合命令

命令行的真正力量在于你开始使用著名的 |,即“管道”,将多个工具串联起来。它将一个命令的输出直接作为下一个命令的输入。

# 获取唯一部门,按字母顺序排列
tail -n +2 messy_data.csv | cut -d',' -f4 | sort | uniq

# 找到薪水 > 55000 的工程师
tail -n +2 messy_data.csv | grep "Engineering" | awk -F',' '$3 > 55000' | cut -d',' -f1,3

# 按部门统计员工数量,并进行计数
tail -n +2 messy_data.csv | cut -d',' -f4 | sort | uniq -c | sort -rn

这里发生的事情是:

  • 每个 | 将前一个命令的结果传递给下一个命令。
  • 你构建了一种“流水线”处理方式,就像工厂的生产线:一个命令进行切割,另一个进行过滤,再一个进行分组,另一个进行排序。
  • 在最后一个示例中, sort -rn 按照数字逆序排序(从大到小)。

示例输出:

工程
市场
销售
   Bob Davis    ,60000
      5 工程
      3 市场
      2 销售

你能看出这些部分是如何相互配合的吗?你从一个简单的CSV开始,通过几个命令,就能得到一个迷你报告。


9. 转换数据格式

在某些情况下,您需要更改文件的“格式”,无论是为了在其他系统中导入,还是为了在某些工具中更好地打开。一个常见的例子是将逗号替换为制表符,从而创建一个TSV文件。

# 将CSV转换为TSV(制表符分隔)
sed 's/,/\t/g' messy_data.csv > data.tsv

现在我们将添加一个固定列,例如,将“2024”这一年添加到所有行中。这可以是报告的年份或参考基础的年份。

awk -F',' 'BEGIN{OFS=","} {print $0, "2024"}' messy_data.csv > data_with_year.csv

详细说明这个 awk

  • BEGIN{OFS=","} 定义输出分隔符为逗号。
  • $0 代表整行输入。
  • print $0, "2024" 打印原始行,并随后添加新列“2024”。

这是一种快速丰富数据的方法,无需打开任何编辑器,就像在电子表格中为每个人插入一整列相同的值。


10. 构建完整的数据清理管道

现在我们将所有内容整合到一个流程中,形成一系列命令,从脏数据文件中提取出一个更为整洁的文件。

# 保存表头
head -n 1 messy_data.csv > final_clean.csv

# 清理数据:去除重复项,修剪空格,删除缺失值的行
tail -n +2 messy_data.csv | \
  sed 's/^[ \t]*//; s/[ \t]*$//' | \
  grep -v ",," | \
  sort | \
  uniq >> final_clean.csv

echo "清理完成!请检查 final_clean.csv"

这个管道实际做了什么?

  1. 确保保留标题,直接写入 final_clean.csv
  2. 跳过标题,仅处理数据行。
  3. 去除每行开头和结尾的多余空格。
  4. 丢弃任何缺少值的行(通过 ",," 检测)。
  5. 对行进行排序并消除重复项。
  6. 将清理后的结果附加到最终文件中。

这几乎就像为电子表格创建一个“智能过滤器”,只不过是以脚本的形式。你可以每天在一个新文件目录中运行这个脚本,例如,确保在将数据发送到数据库或Python之前,数据始终更有条理。


结束想法

在命令行中清理数据是一项默默无闻的技能,它不会在美丽的图表中显现,但对处理CSV、日志、系统导出和杂乱表格的人来说却有着巨大的影响。这些工具快速、可靠,并且与Python及其他语言非常兼容:你仍然可以使用你的笔记本,只是到达那里时会少一些杂乱。

更有趣的是,这一切不仅仅适用于自认为是“数据科学家”的人。直接在终端中处理数据对数据工程、DevOps、系统管理以及任何需要重复处理大文本文件的日常工作都有帮助。

如果你开始用自己的文件进行练习——客户列表、从银行导出的对账单、在线商店的销售CSV、学术系统的报告——你会发现许多乏味的任务从你的日常工作中消失。随着时间的推移,你会越来越想用几条命令在终端中解决小数据问题,而不是为了快速清理而打开一个沉重的笔记本。

更多