收藏本站 劰载中...网站公告 | 吾爱海洋论坛交流QQ群:835383472

资源 | 简单快捷的数据处理,数据科学需要注意的命令行

[复制链接]
- P: ^6 T3 o" H4 S# ]$ s/ D
2 U/ r; [0 \% |. ~( x" p6 h: c# y
8 K; _- N: T! }" t$ X! n- w2 R" }9 a
原标题:资源 | 简单快捷的数据处理,数据科学需要注意的命令行 选自Medium 作者:Kade K
- F7 x H5 q/ `( R
6 Y6 @( @* h7 q& G/ c+ c
- k4 a4 c5 T* u, A- E% ?
- A. H1 ^1 p# P, t1 }

原标题:资源 | 简单快捷的数据处理,数据科学需要注意的命令行

$ e" ~! B8 Y6 S+ n# f, K1 m. b

选自Medium

, y4 J6 Q) C4 Q* R( c6 ~1 g# P" U% y

作者:Kade Killary

2 H& Y \) z8 x! t2 z! v3 s" T7 ]

机器之心编译

{1 U: y% h: y8 M: N' T' F: ]

参与:Nurhachu Null、思源

1 p/ u% l- D) g: t v7 ?( e

对很多数据科学家而言,他们的数据操作经常需要使用 Pandas 或者 Tidyverse。理论上,这个说法没有任何错误,毕竟这就是这些工具存在的原因。然而,对于分隔符转换这样的简单任务而言,这些工具往往是大材小用,我们可以直接使用命令行快速处理。

0 P6 K* A3 w) G+ s" F4 Q

命令行应该是每个开发者都希望掌握的,尤其是数据科学家。熟悉终端的来龙去脉可以毫无疑问地可以让我们变得更加有效率,因此命令行还是计算机技术中的一个很棒的历史课。例如,awk 这个数据驱动的脚本语言是 1977 年在 Brina Kernighan 的帮助下首次出现的,Brina Kernighan 就是 K&R 这本书中的 K。在 50 年后的今天,每年仍然能够出现与 awk 相关的新书。因此,我们可以相对保守地假设:一项针对命令行才能的投资在任何新近的时间内都不会贬值。

+ H' x/ l9 m3 @* N2 }8 n
- R, J* c. h/ p/ @
2 v: l" X+ A7 w6 h3 T% G! B' _
打开凤凰新闻,查看更多高清图片
, C% O6 L& v/ K. O
# p$ I2 L# M2 L
2 R' ~' A6 ~. o7 |. E! \

我们将会涉及以下内容

# n* X3 v z2 L

ICONV

( g+ D/ z" G7 |* d* b

HEAD

5 d& @2 O: `$ _5 g$ t

TR

3 [1 d- p1 N+ W( u, _2 V6 J& P

WC

8 m. W9 c* ~( @

SPLIT

7 Q' p1 V5 e5 m9 T4 {& }# N7 v. R# j! h

SORT & UNIQ

! d! M) e( q% E6 Z: i

CUT

$ e, V1 D) F7 d

PASTE

9 f [ B5 }0 f* u: |0 z" Q

JOIN

5 _7 ]9 J2 Y8 m9 w" A8 J

GREP

% ?( G$ g4 r) g& n

SED

+ t' Y0 o$ t7 F6 |. o1 b) L! ^

AWK

& F5 V3 L, X) e; n' h/ G

ICONV(用来转换文件的编码方式)

0 t, ^/ J; C; K# F

文件编码可能是比较棘手的。现在的多数文件都是 UTF-8 编码,然而有时候我们拿到的文件并不是这个格式的。这可能导致交换编码格式时的一些不靠谱的尝试。这里,iconv 是一个拯救者,它能以一种编码的文本为输入,输出另一种编码的文本。

# Converting -f (from) latin1 (ISO-8859-1)# -t (to) standard UTF_8iconv -f ISO-8859-1 -t UTF-8/ e. s A7 V! ?% h$ Z( O0 T k# c+ u6 F; k

< input.txt > output.txt

% ~' ~/ h9 p" B3 e X: s

可选参数:

- r4 f& w3 x" G$ a. \& s. I

iconv -l 列出所有已知的编码字符集合

% x. x7 V" A6 _8 A, h( K3 v# j* U/ Z

iconv -c 忽略不能转换的非法字符,静默地丢弃

0 M4 r2 C' e6 x: f) s5 p

HEAD(用于显示文件的开头内容)

4 t, h$ I# o7 s' u D

如果你是一个频繁使用 Pandas 的用户,那么你会比较熟悉 df.head()。默认情况下 head 命令显示文件的前 10 行内容,当然我们也可以选择不同的参数确定打印的行数或字符数。

# Prints out first 10 lines- i* P/ _* Q0 d5 Q+ H

head filename.csv

# Print first 3 lineshead -n 33 m$ b5 }0 J- A# U6 Z

filename.csv

+ O; j: B% p# p* U

可选参数:

" [/ r3 l2 l: x/ `

head -n <数字> 打印特定数目的行数

) f, e4 y, s: N5 g" y

head -c <字符数> 打印特定数目的字符

7 z9 c) z/ O* c* N$ U s/ H

TR(对字符进行替换、压缩和删除)

: i+ J+ m$ C- ]5 y( y& @7 ]# d3 I2 G8 P- @

tr 与转译比较类似,它的强大能力是文件清理的主要工具。例如以下交换文件中的分隔符:

# Converting a tab delimited file into commascat tab_delimited.txt | tr "\\t" "," comma_delimited.csv

tr 的另一个功能是由我们控制的内置 [:class:] 参数,这些用法包括:

# R' F' M4 v% j1 Y9 W

[:alnum:] 所有的字母和数字

4 j; l4 k3 c$ L+ C6 E

[:alpha:] 所有的字母

, S ~( G& d3 ~8 S% g/ `& A

[:blank:] 所有的水平空格

% _& M# ~ L5 q/ A7 J

[:cntrl:] 所有的控制字符(非打印)

2 p4 D& I& x6 t3 [; P8 H

[:digit:] 所有的数字

5 n- o9 ?; `: y% g: ^2 l

[:graph:] 所有的可打印字符,不包含空格

! J6 R" z, r# K/ ~: T' f9 P6 o

[:lower:] 所有的小写字母

& s5 t0 Y! n- s/ v8 q- X; w

[:print:] 所有的可打印字符,包含空格

V+ j5 B% D8 p* y

[:punct:] 所有的标点符号

* ~9 y/ j: d$ L

[:space:] 所有的水平或垂直空格

' I& u/ y% Y, m. o2 _! ^2 S g

[:upper:] 所有的大写字母

- `5 [" q' n4 @- C

[:xdigit:] 所有的十六进制字符

& D6 k6 L G) J/ X; x

我们可以将它们连接在一起组成强大的程序。下面是一个基本的字数统计程序,我们可以用它来检查 README 文档。

cat README.md | tr "[:punct:][:space:]" "\n" | tr "[:upper:]" "[:lower:]" ; g, ~; w0 k+ {. W+ I

| grep . | sort | uniq -c | sort -nr

; Y8 J: n h; [5 W% K8 H( _

使用基本正则表达式的另一个例子是:

# Converting all upper case letters to lower casecat filename.csv | tr [A-Z] [a-z]7 H/ A! k8 I# a

可选参数:

& C* w4 a1 X. Q8 x g( o

tr -d 删除字符

/ N z* C9 Y0 w, H8 Q0 R

tr -s 压缩字符(将连续重复的字符用一个字符表示)

, M- m% a* ~ t6 ~* r

\b 空格

) F) E7 n: G& x" x

\f 换页符

0 @( b5 K% D! Z. M- f/ p

\v 垂直制表符

# ` w/ w# D/ V% s

\NNN 八进制字符 NNN

1 T! O5 o2 x$ q$ u' r

WC(用来计数的命令)

9 D4 A# Z: Y4 S$ t9 v

它的值主要来自于 -l flag,它会提供文档的行数。

# Will return number of lines in CSVwc -l gigantic_comma.csv

这个工具可以方便地确认各种命令的输出。所以,如果我们转换了文件中的分隔符,那么运行 wc -l 就可以查看总行数是不是相同,不同就是出了问题。

: V& J' k6 |, G8 Z! x& R

可选参数:

! I, Y" ~/ W; x0 E# w( d% {

wc -c 打印 Bytes 数目

/ a2 N/ c$ _% |. ^% t

wc -m 打印出字符数

0 ^3 J0 z6 \* M) D/ t- C

wc -L 打印出最长行的字符数

( g) n! y' @; C; N

wc -w 打印出单词数目

9 J4 u" y- U ]& g2 k, c, m6 X6 W

SPLIT(把一个大文件分割成小文件的命令)

1 A" Z! q( e+ R& Y" _- j8 `; ?

文件大小可以使用这个命令大幅度改变。根据任务的不同,分割文件可能会有所帮助,所以就有了 split 命令。split 的基本语法如下:

# We will split our CSV into new_filename every 500 linessplit -l 500+ v1 O" x/ R3 E6 V

filename.csv new_filename_

# filename.csv# ls output# new_filename_aaa# new_filename_aab# new_filename_aac a9 h. t+ v5 F. c! K

两个怪异的地方是命名约定和文件的扩展名。后缀约定可以通过-d 标志来约定为数字。为了添加文件扩展名,您需要运行下面的 find 命令。它会改变当前路径下的所有文件名,给每个文件后面扩展.csv,所以,谨慎使用。

find . -type f -exec mv {} {} 2 U5 B, I- r% ~1 }

.csv \;

# ls output# filename.csv.csv# new_filename_aaa.csv# new_filename_aab.csv# new_filename_aac.csv% P* C+ o/ P, A

可选参数:

; ~ Z" u1 ?1 L

split -b 通过确定的字节大小分割

3 _' {- Z6 z. W# Z9 J3 a2 A6 u% [& N

split -a 生成长度为 N 的后缀

4 `+ a% |2 W6 w. M! y

split -x 使用十六进制后缀分割

% _( C( q9 S9 d6 S- H

SORT & UNIQ(sort:文件排序;uniq:报告或忽略文件中的重复行,与 sort 结合使用)

1 S+ {/ [$ i. B2 y$ w

这两个命令提供了唯一的单词计数,这是因为 uniq 仅仅在重复的相邻行上运行。因此,这就是在输出之前进行排序的原因。一个有趣的注意事项是:sort -u 会与 sort file.txt | uniq 有着相同的结果。

3 x2 Q0 ^4 L, }- b# p$ f$ M0 t1 p

对于数据科学家而言,排序具是一种潜在有用的能力:即基于特定列对整个 CSV 文件进行排序的能力。

# Sorting a CSV file by the second column alphabetically . C ]. `/ E( ?" E- Y6 y) m; z

sort -t, -k2 filename.csv

# Numerically# [3 Z* ?1 ^/ l8 T

sort -t, -k2n filename.csv

# Reverse ordersort -t, -k2nr filename.csv

这里的-t 选项将逗号作为我们的分隔符,通常会采用空格或者制表符。此外,-k flag 用于指定关键词。

, J! k3 {2 ^; p# }

可选参数:

$ K+ C! d, b1 e4 X0 `( n- R

sort -f 忽略大小写

# y+ k7 e! |1 z( Z S

sort -r 以相反的顺序排序

- ^/ X7 I. o: V

sort -R 乱序

: O; f! ~$ k* K+ e

uniq -c 统计出现的次数

/ j8 p) O& A8 B+ `

uniq -d 仅仅打印重复行

# w/ Q" }, \# f! P

CUT(cut 命令用来显示行中的指定部分,删除文件中指定字段。)

. C0 h" }9 I1 ?2 ?

cut 用于删除列。举例来说,如果我们要删除第一列和第三列,可以使用 cut:

cut -d, -f 1,3 filename.csv

选择除了第一列之外的每一列:

cut -d, -f 2- filename.csv

与其他命令结合使用的时候,cut 作为一个过滤器:

# Print first 10 lines of column 1 and 3, where "some_string_value" is presenthead filename.csv | grep "some_string_value" | cut -d, -f 1,3! _8 N+ L# b% Z0 x8 t" v

找到第二列中某个特定值出现的次数:

cat filename.csv | cut -d, -f 2& k; c( B7 m: r

| sort | uniq | wc -l

# Count occurences of unique values, limiting to first 10 resultscat filename.csv | cut -d, -f 2 | sort | uniq -c | head

PASTE(用于将多个文件按照列队列进行合并)

7 [4 `! ]. p( |8 l

paste 是一个简洁命令,具有一个有趣的功能。如果您有两个需要合并的文件,并且它们已经排序,paste 能够实现这些功能。

# names.txt , a+ V, ~* O7 K C/ s8 y% L" n# e

adam

( |" e7 }; b2 T6 V" r: Y& a! W, X

john

& i( ?- e- I$ s" R3 z

zach

# jobs.txt8 R* f. B1 [( j

lawyer

, l( m" u4 o5 h# ?+ |) [

youtuber

, R3 ]& K4 T1 s2 L" S6 T( t. Y7 d; r

developer

# Join the two into a CSVpaste -d ,' z, P3 G) H$ u! n1 ]! b& A/ }

names.txt jobs.txt > person_data.txt

# Output$ a+ z% ?; u8 t: B. R( Q0 R- ?

adam,lawyer

. F8 _7 ?/ L# n. ]

john,youtuber

zach,developer

更具 SQL 风格的变体,请参见下文。

1 l3 |- U K8 X) x i; N! F! n8 F

JOIN(连接并合并文件)

) B% A9 T0 w5 K5 W" N

join 命令是一个简单的、拟正切的 SQL。最大的区别在于 join 将返回所有列,并且只能在一个字段上进行匹配。默认情况下,join 将尝试使用第一列作为匹配键。对于不同的结果,必须使用以下语法:

# Join the first file (-1) by the second column# and the second file (-2) by the firstjoin -t, -1 2 -2 1 - ^4 x+ c" r; V- {& F2 k& z$ Z

first_file.txt second_file.txt

+ z8 w1 u6 g7 D! K! A# p# A9 T; B

标准 join 是内部连接。但是,外部连接也可以通过- a flag 实现。另一个值得注意的现象是- e 标志,如果找到丢失的字段,它可以用来替换值。

# Outer join, replace blanks with NULL in columns 1 and 2# -o which fields to substitute - 0 is key, 1.1 is first column, etc...join -t, -1 2 -a 1 -a2 -e NULL -o 0,1.1,2.2 first_file.txt second_file.txt

虽然不是最便于用户使用的命令,但是绝望的时候自有绝望的措施。

, |2 h" X# b, b. l

可选参数:

; ?) {) O# k& I, w2 N' E) J( f; G

join -a 打印不能匹配的行

. q5 _( A: Q1 ]/ w- E1 [

join -e 替换丢失的输入字段

9 \) T2 i+ O$ z0 t1 U3 x5 t$ Y

join -j 等价于 -1 FIELD -2 FIELD

! U1 @4 p$ r, p3 ^1 _7 `- u

GREP(这是一种强大的文本搜索工具)

! y6 _7 S, P: Y f8 Y. ^; g

全面搜索正则表达式并打印(grep),这很可能是最出名的命令。grep 有很多强大的能力,尤其是在大型代码库中以我们自己的方式寻找字段。在数据科学领域,它充当着其它命令的细化机制。

# Recursively search and list all files in directory containing wordgrep -lr word& c& V ^( }0 ~9 X

.

# List number of files containing wordgrep -lr word . | wc -l

统计包含单词/模式的总行数

grep -c some_value! M4 s; ^0 Z8 b$ J

filename.csv

# Same thing, but in all files in current directory by file namegrep -c some_value *

使用\|运算子进行多值操作

grep "first_value\|second_value" filename.csv

可选参数:

0 S/ |' v6 o7 ]! i. u+ x

alias grep="grep --color=auto" 使 grep 色彩化

u$ Y8 B0 V7 ~7 X" H/ U

grep -E 使用扩展的正则表达式

. m# W) A% t+ i- |* D1 ^3 @; z& L

grep -w 只匹配全字符

- c8 b; i; h# R ]: \

grep -l 打印出匹配的文件名

$ U: P g, L4 o" M& `1 j9 [

grep -v 反转匹配

& b1 [5 O. y5 O) F+ ]

SED(流编辑器)

! U" W+ p. y; o3 [$ b# V; I

sed 是一个逐行运行的流编辑器。它擅长替换,但是也可以用于所有的重构(refactoring)。

5 H$ }" B# z4 f+ a

最基本的 sed 命令包含 s/old/new/g。这指的是搜索旧值,并用新值替换。如果没有/gour 命令,终端将在第一次出现这个值之后停止。

; I9 l) @! B$ U" }

为了快速体验这种能力,让我们来举个例子。若我们有以下文件:

9 Y7 W, R; s4 Y0 P: O0 Z

balance,name

$1,000 1 T! L; ^) U7 I( m7 P

,john

$2,000,jack

我们想做的第一件事就是去掉美元符号。-i flag 指的是位置,标志指的是零长度的文件扩展名,然后覆盖初始文件。理想情况下,我们可以单独测试其中的每一个,然后输出到新文件。

sed -i s/\$//g' `$ S" Q0 O% j$ R2 H5 X- H

data.txt

# balance,name# 1,000,john# 2,000,jack 8 N6 I3 ~2 J5 M* q! ]

接下来,我们处理 balance 中的逗号

sed -i s/\([0-9]\),\([0-9]\)/\1\2/g! w8 Q! v$ o0 N$ P+ r+ n# ^, a1 J" i6 K

data.txt

# balance,name# 1000,john# 2000,jack ) m' S) n1 E3 g/ W

AWK(不仅仅是一个命令)

j% F) [4 L; S. {. W: ~6 h1 X, o

awk 不仅仅是一个简单的命令:它是一种成熟的语言。在本文所涉及的所有内容中,awk 是最酷的。如果你发现自己对 awk 印象深刻,也可以找更多的资源。

' S6 V. c- L2 ?5 r5 k

 awk 的用例包括:

/ s* L# P% U6 [5 U ?

文本处理

0 ~/ v$ ?5 w9 X7 i; L5 C

格式化文本报告

/ B3 g& `) {* R- {; N' Q

执行数学运算

) ^" g) |4 U' x$ ]; ?* g4 N

执行字符串操作

$ T2 ^: c c2 i# `2 D& |

最新版的 awk 可以与 grep 并行使用。

awk /word/ filename.csv

或者使用一些技巧将 grep 和 cut 结合起来。这里,对于所有我们要查找的 word 行,awk 打印第三列和第四列和分隔符。-F,仅将分隔符改为逗号。

awk -F, /word/ { print $3 "\t" $4 } filename.csv

awk 内置了许多优秀的变量。例如,NF -字段数,NR -记录数。要在文件中获取第五十三条记录,代码如下:

awk -F, NR == 53 filename.csv

一个额外的功能是基于一个或多个值进行过滤的能力。下面的第一个示例将打印第一列等于 string 记录的行数和列数。

awk -F, $1 == "string" { print NR, $0 } 5 _! o5 H9 e7 c) E9 k0 E0 K9 g

filename.csv

# Filter based off of numerical value in second columnawk -F, $2 == 1000 { print NR, $0 } filename.csv

多数值表达式:

# Print line number and columns where column three greater# than 2005 and column five less than one thousandawk -F, $3 >= 2005 && $5 <= 1000 { print NR, $0 } filename.csv

对第三列求和:

awk -F, { x+=$3 } END { print x } filename.csv

对第一列等于『something』的所有行,对它们的第三列求和。

awk -F, $1 == "something" { x+=$3 } END { print x } filename.csv

得到文件的维度:

awk -F, END { print NF, NR }# M K" N8 s! b/ o' ]3 d

filename.csv

# Prettier versionawk -F, BEGIN { print "COLUMNS", "ROWS" }; END { print NF, NR } filename.csv

打印出现两次的行:

awk -F, ++seen[$0] == 2 filename.csv

删除重复的行:

# Consecutive linesawk a !~ $0; {a=$0} # b+ }: K: s& ` [" q g( F, i. `

]

# Nonconsecutive linesawk ! a[$0]++ ( y# A# D5 U! X F

filename.csv

# More efficientawk 4 l4 S' `+ F2 O5 B) P2 w

!($0 in a) {a[$0];print}

6 a$ S: u; d& Z. l/ X* S0 `& x
; ]9 X0 u' k; k3 _) q' L- e+ Q2 R

使用内置函数 gsub() 替换多值:

awk {gsub(/scarlet|ruby|puce/, "red"); print}& w9 q# p+ z8 K" l% H/ y$ M

这个 awk 命令将合并多个 CSV 文件,忽略文件头,然后将其附加到末尾。

awk FNR==1 && NR!=1{next;}{print} *.csv > final_file.csv

需要缩减大量文件?awk 可以在 sed 的帮助下处理这个问题。具体而言,这个命令可以基于行数将 一个大文件拆分为多个小文件。

sed 1d;$d filename.csv | awk NR%NUMBER_OF_LINES==1{x="filename-"++i".csv";}{print > x}# Example: splitting big_data.csv into data_(n).csv every 100,000 linessed 1d;$d big_data.csv | awk NR%100000==1{x="data_"++i".csv";}{print > x}) g6 C( o& L( g+ {6 y

结语

; e( G4 B$ k* |# ?6 N$ W

命令行拥有无穷无尽的能力。本文中介绍的命令足以让您在短时间内从小白变成高手。除了这些内容之外,还有许多用于日常数据处理的程序需要考虑。如果你想深入了解命令行数据科学,可以多找一些详细的资源。

% n3 Q/ @" J4 S& a+ w4 }9 V2 i) j

原文链接:

$ y ?5 H: ?3 E1 `( \( Q

https://medium.com/@kadek/command-line-tricks-for-data-scientists-c98e0abe5da

$ s& W& V7 [0 E2 W+ T% v# c

本文为机器之心编译,转载请联系本公众号获得授权

) W' i2 E8 m# V( {

✄------------------------------------------------

9 `! N- {: u: ?

加入机器之心(全职记者/实习生):hr@jiqizhixin.com

. p0 q) H& g$ G- g9 C! o

投稿或寻求报道:content@jiqizhixin.com

% B+ A& r% s( Y& [% h3 {" j

广告&商务合作:bd@jiqizhixin.com

$ v. ]/ ~6 D9 T9 \, a1 b0 b
. A+ N" \4 L5 B9 ]9 X
2 m, Q0 [; o1 D6 Q: _
8 [2 I* l# D+ B3 c9 g# E , V% I4 y/ r2 G% J! [9 Q+ _# c 1 T6 W& T( j. @3 {9 G2 I7 v0 d9 A" V8 |3 [: j+ ~ ~! x K+ K5 n( Y0 D
回复

举报 使用道具

相关帖子

全部回帖
暂无回帖,快来参与回复吧
懒得打字?点击右侧快捷回复 【吾爱海洋论坛发文有奖】
您需要登录后才可以回帖 登录 | 立即注册
华德地毯
活跃在2026-4-5
快速回复 返回顶部 返回列表