8个有用的Shell数据科学命令

本文概述

  • 快速笔记
  • 用wc计数
  • 用cat连接文件
  • 用sed修改文件
  • 子集大文件
  • 使用uniq查找重复项
  • 选择带有剪切的列
  • 循环播放
  • 变量
  • 总结
在许多情况下, 你需要快速分析, 修改和处理数量和大小较大的文件。但是, 文件通常是基于文本的逗号分隔值(CSV)文件。使用标准电子表格应用程序(例如Excel, LibreOffice或OpenOffice)打开它们会使计算机的内存过载。另外, 由于一些意外的文件异常, 一批处理大量文件通常在几个小时后失败。
你不可避免地会在冻结屏幕, 重新启动和长时间等待上花费大量时间。
但是, 大多数这些任务可以用几行代码来完成。而且, 熟悉一些简单的shell命令行可以大大节省时间并减少挫败感。
这篇文章将概述我几乎每天都使用的一些shell命令。希望你觉得它们有用。
8个有用的Shell数据科学命令

文章图片
快速笔记 请注意, shell的类型不同(bash, zsh等), 其中bash shell最为常见, 因为它是OS X和主要linux发行版上的默认shell。 Zsh(还有Oh My Zsh)是一种流行且功能强大的替代方案。此博客文章中包含的shell命令已经在OS X(macOS)上的bash上进行了测试, 并且可以与其他shell和环境一起使用。
以下所有示例均基于UCI机器学习存储库中的成人数据集, 也称为” 普查收入” 数据集, 可在此处获取。此数据集通常用于根据普查数据预测收入是否超过\ $ 50K /年。拥有48842行和14个属性, 到目前为止, 它并不是一个很大的数据集, 但足以说明这些示例。尽管数据以.data扩展名存储, 但它是格式正确的CSV文件。随时下载数据集以继续学习!
用wc计数 给定一个基于文本的新文件, 你想知道它包含多少行。这可以通过单词count wc -l命令来完成:
$ wc -l adult.data 32562 adult.data

告诉你Adult.data文件包含32562行。 -l标志告诉wc计算行数。但是你也可以使用wc代替-w标志来计数单词。
$ wc -w adult.data 488415 adult.data

【8个有用的Shell数据科学命令】adult.data文件包含近50万个字。
通过使用简单的ls -l命令的输出作为wc的输入, wc命令还可以计算目录中的文件数。使用管道符号|将命令的输出用作另一个命令的输入是一种有用的shell模式, 称为流水线。在整个文章中, 你将在几个示例中看到它。
假设现在你有一个包含许多文件的文件夹。以下命令将准确告诉你它包含多少个文件:
$ ls -l < folder> | wc -l 508

如果你开始添加通配符和子文件夹, 则wc还有许多其他应用程序。
让我们回到你的adult.data文件, 并使用head命令查看第一行。默认情况下, head输出10行, 你可以使用-n标志将输出限制为前2行。
$ head -n 2 adult.data 39, State-gov, 77516, Bachelors, 13, Never-married, Adm-clerical, Not-in-family, White, Male, 2174, 0, 40, United-States, < =50K 50, Self-emp-not-inc, 83311, Bachelors, 13, Married-civ-spouse, Exec-managerial, Husband, White, Male, 0, 0, 13, United-States, < =50K

并且你注意到该文件没有标题行。列名不在文件内。你可以通过使用cat命令连接两个文件来添加该标题行。
用cat连接文件 cat命令将文件的内容打印到标准输出(也就是你的终端)上。它也可以用来连接一系列文件。命令cat file_1.csv file_2.csv> target_file.csv会将file_1.csv和file_2.csv的内容合并到target_file.csv中, 并在file_1.csv的末尾添加file_2.csv。
头文件不在原始数据集中, 你需要创建它。为此, 你将以逗号分隔的列名列表回显到header.csv文件中。
$ echo "age, workclass, fnlwgt, education, education-num, marital-status, occupation, relationship, race, sex, capital-gain, capital-loss, native-country, class" > header.csv

在此示例中, 你使用了shell重定向> 字符将cat的输出转储到adult.csv文件中。 > 将创建文件或完全替换其内容(如果文件已存在)。加倍符号> > 会将新内容附加到现有文件中, 而不会擦除其内容。
现在让我们将header.csv文件添加到adult.data文件的开头。同时, 将adult.data重命名为adult.csv, 因为它毕竟是CSV格式的文件。
$ cat header.csv adult.data > adult.csv

检查Adult.csv的第一行是否包含具有以下内容的列名:
$ head -n 1 adult.csv age, workclass, fnlwgt, education, education-num, marital-status, occupation, relationship, race, sex, capital-gain, capital-loss, native-country, class 39, State-gov, 77516, Bachelors, 13, Never-married, Adm-clerical, Not-in-family, White, Male, 2174, 0, 40, United-States, < =50K

用sed修改文件 当文件损坏或格式错误(例如, 非UTF-8字符或逗号不正确)时, 会发生另一种频繁的数据挖掘情况。你可以纠正该文件, 而无需使用sed命令实际打开它。
通用sed模式是
$ sed "s/< string to replace> /< string to replace it with> /g" < source_file> > < target_file> .

adult.csv数据集使用?表示缺失值的字符。你可以使用sed将其替换为更适合的默认值。最好使用空字符串来表示缺少的值, 因为在将数据加载到Pandas DataFrame中时, 它将被解释为NaN值。
$ grep ", ?, " adult.csv | wc -l 2399

这样一来, 你可以算出2399行, 其中至少一列的缺失值用?表示。以下命令将所有列替换为?用一个空字符串。所有仅包含?, 后跟一个空格的单元格现在将真正为空。
$ sed "s/, ?, /, , /g" adult.csv > adult.csv

请注意, 在源字符串和目标字符串中使用列定界符, 以避免替换可能出现在数据集中其他地方的合法问号。
子集大文件 现在想象一下, 你要处理的文件超过3000万行。在制作Python或R脚本时, 你将只想在原始大文件的样本上测试工作流, 而不必将整个数据集加载到内存中。你可以组合使用头和尾来创建原始数据集的子样本。
  • head输出文件的第一部分;
  • 尾巴输出文件的最后一部分
如你之前所见, 这些命令带有-n标志, 代表– lines, 它限制了输出中的行数。尾部还带有-f标志, 其中f代表– follow, 当将行添加到文件末尾时, 它将输出附加数据。当脚本使用tail -f < logfile> 运行时, 这对于监视日志文件特别方便。
混合在管道符号中|使用头和尾, 你可以从源文件中提取一定数量的行, 并将内容导出到子文件。例如, 要提取从第100行开始的20行:
$ head -n 120 adult.csv | tail -n 20 > adult_sample.csv

请注意, 你首先将first_line + number_of_lines放在头, 然后在number_of_lines尾部放置。通用子设置命令为:
$ head -n < total_lines> < source_file> | tail -n < number_of_lines> > < target_file>

其中total_lines = first_line + number_of_lines。但是, 新的采样文件不再包含标题行。我们已经知道如何使用cat将标头重新添加到子文件中, 以连接子文件和之前创建的header.csv文件:
$ cat adult_sample.csv header.csv > adult_sample_with_header.csv

请注意, 你没有使用源文件名” adult \ _sample.csv” 作为目标文件名, 而是创建了一个名为” adult \ _sample \ _with \ _header.csv” 的新文件。使用cat时与源之一和目标名称相同, 将导致意外的文件内容。最好创建一个新文件作为cat命令的输出。
使用uniq查找重复项 使用uniq命令, 你可以在文件中找到相邻的重复行。 uniq带有几个标志, 更有用的是:
  • uniq -c:将重复计数添加到每一行;
  • uniq -d:仅输出重复的行;和
  • uniq -u:仅输出唯一的行。
但是, uniq不是明智的命令。如果重复的行不相邻, 则不会被检测到。这意味着你首先需要对文件进行排序。此命令将统计adult.csv中重复的行数。
$ sort adult.csv | uniq -d | wc -l 23

并显示有23个重复项。下一条命令获取具有重复计数的所有行的输出, 以反向排序并输出前3个重复项:
$ sort adult.csv | uniq -c | sort -r | head -n 3 3 25, Private, 195994, 1st-4th, 2, Never-married, ... 2 90, Private, 52386, Some-college, 10, Never-married, ... 2 49, Self-emp-not-inc, 43479, Some-college, 10, Married-civ-spouse, ...

通过将sort和uniq与不同的标志结合使用, 可以获得许多强大的选项。使用man sort和man uniq进一步探索这些命令。
选择带有剪切的列 CSV文件和Shell命令的妙处在于, 你还可以通过使用cut选择特定列来在列级别进行工作。 cut具有两个主要标志:-d指定列定界符, 和-f指定要处理的列。在下面的示例中, 你将使用cut来查找分类变量workclass(第2列)采用的唯一值的数量。
首先选择列工作类并直达标题以确认你具有正确的列:
$ cut -d ", " -f 2 adult.csv | head -3 workclass State-gov Self-emp-not-inc

现在, 要计算唯一性, 你可以对cut的输出进行排序并将结果通过管道传递给uniq -c, 如下所示:
$cut -d ", " -f 2 adult.csv | sort | uniq -c 1837 960Federal-gov 2093Local-gov 7Never-worked 22696Private 1116Self-emp-inc 2541Self-emp-not-inc 1298State-gov 14Without-pay 1 workclass

例如, 这告诉你你有1837个空值, 并且主类到目前为止是具有22969次出现的Private类。
上面的命令行类似于应用于包含Adult.csv数据的DataFrame的value_counts()方法。
循环播放 到目前为止, 你基本上只处理一个文件。要重命名, 处理或传输大量文件, 应将循环添加到我们的Shell工具箱中。 bash shell中循环的通用格式为:
while true; do _do something_ ; done

让我们开始吧。假设你有1000个文件名, 文件名中带有空格, 而你想用一个非下划线的” _” 替换每个空格。
replace_source=' ' replace_target='_' for filename in ./*.csv; do new_filename=${filename//$replace_source/$replace_target} mv "$filename" "$new_filename" done

在这个例子中
  • 首先, 声明两个变量:replace_source和replace_target作为空格和下划线字符的占位符
  • 你遍历当前文件夹中的所有* .csv文件
  • 对于每个文件名, 你可以通过用下划线替换每个空格来创建一个new_filename
  • 然后使用mv命令将文件从当前文件名重命名为新文件名
实际上, 不仅使用shell循环浏览目录中的文件, 还创建了变量。
变量 你将以变量结尾此shell命令介绍。在shell中创建变量只需通过
$ varname='< a string> ' $ varname=a number

例如:
$ varname='Hello world' $ varname=123.4

请注意, ” =” 符号周围没有空格。 var ='< a string> ’ 将不起作用。要返回变量值, 只需回显它:
$ echo $varname 123.4

要在脚本中使用它, 请将其封装在引号中, 如前所述:
$ mv "$filename" "$new_filename"

编写循环和使用变量为更复杂的文件操作打开了方便之门, 并且是shell脚本的门户, 这超出了本文的介绍。但是, 如果你从小处着手, 并随着信心的提高而提高, 那么shell脚本就足够简单了。
总结 Shell命令行作为数据科学家在你的日常工作中非常有用。还有更多示例和用例可以探索。正如你将看到的, 使用各种各样的可用shell命令和相关标志通常总是有不同的方法来达到特定的结果。在这种情况下, 保持简单永远是制胜法宝。
希望这里提供的示例将帮助你将Shell命令集成到数据处理工具包中。随时与我联系并在Twitter上分享你的Shell技巧:@alexip。

    推荐阅读