数据处理常用Unix命令
背景
昨晚半夜放了个小福利,去年的25g数据。下载之后,一打开就死机。一个csv文件就有800多m,我们该怎么办?
连csv文件里面包含的内容,我们都不知道,此时,该如何导入到数据库中来处理?
对于这种动不动近1G的洗数据任务,一般的文本编辑器都会死掉。常用的Unix命令更胜任。以数据包中的week1.csv文件为例。假设你下载的文件地址保存在: ~/Dropbox/dataset。以下操作均在该目录下进行。
week1.csv文件解压之后是893m。我们打开iterm2或者其它终端,这么来处理。
显示前后记录:head与tail
显示前5条记录,输入:
head -n 5 week1.csv
求出:
mid,retweeted_status_mid,uid,retweeted_uid,source,image,text,geo,created_at,deleted_last_seen,permission_denied
mCClUNCqwe,mU5j0dIAkQ,uK3RXUJ0V,,新浪微博,0,转发微博,,2012-01-03 02:02:27,,
mRsOcOLTlc,mJGNX5nAmo,uK3RXUJ0V,,新浪微博,0,!!!!!!!!!@uK3RXUYW3: //@u0AGMTTVD: !!!!!!!!,,2012-01-03 01:17:39,,
mH44qG6iUm,mH44qL9LlF,uK3RXUJ0V,,新浪微博,0,求一切順利!!!,,2012-01-03 01:15:36,,
mZmwFtOdVX,mcyE5GR7GJ,uK3RXUJ0V,,新浪微博,0,想要><@uK3RXUYW3: //@ukn: 全都想要啊QAQ,,2012-01-03 01:12:55,,
第一行输出的关键信息,这是非常关键的,表示列名,后续的查找与过滤,我们均基于此。
mid,retweeted_status_mid,uid,retweeted_uid,source,image,text,geo,created_at,deleted_last_seen,permission_denied
显示后5条记录,输入:
tail -n 5 week1.csv
求出:
mf6YmAD22X,m4wDEUUgDS,u5KYV4BIS,,iPhone客户端,0,//@ukn: // @u3FT1GL1R: : // @ukn: : // @ukn: : // @ukn: : 轉發微博,,2012-01-08 23:23:55,,
m7K7nzB6Jg,mGvPLXcfzj,u5KYV4BIS,,iPhone客户端,0,//@ukn: // @ukn: : // @ukn: : [惊哭]// @ukn: : 0.0,,2012-01-08 23:23:38,,
mSaCPHfcGY,mFLRQ5Def6,u5KYV4BIS,,iPhone客户端,0,//@ukn: 这是TR时候的吧? // @ukn: :这是什么东西- -// @ukn: : 嗷 不要那么看着我啊。// @uDZPXZSA0: : 我去!!!!!!![飙泪中],,2012-01-08 23:23:04,,
mB1eQ3YRS5,mr3Zm5gRna,u5KYV4BIS,,iPhone客户端,0,//@ukn: // @ukn: : // @ukn: : // @ukn: : // @uPA3JIQ33: : // @uDZPXZSA0: : 这么好的颜不当颜饭都可惜了[泪]// @ukn: : // @ukn: : 颜太美好了┭┮﹏┭┮ 邮递员神剧啊,,2012-01-08 20:43:13,,
mA3atazmJ6,,uTS2D03EM,,Android客户端,1,@uVGJC2VMO: 肥兔子生日快樂!!!![鼓掌][鼓掌][干杯][干杯][干杯][蛋糕][蛋糕][蛋糕][蛋糕][蛋糕]新的一年一切都要順順利利~心想事成啊[亲亲]永遠都白白胖胖的[兔子][兔子]蛋糕很好吃~[爱你][可爱],,2012-01-08 21:59:53,,
排序:sort
接下来,我们对刚才求出的前5条记录进行排序。
head -n 5 week1.csv | sort
求出:
mCClUNCqwe,mU5j0dIAkQ,uK3RXUJ0V,,新浪微博,0,转发微博,,2012-01-03 02:02:27,,
mH44qG6iUm,mH44qL9LlF,uK3RXUJ0V,,新浪微博,0,求一切順利!!!,,2012-01-03 01:15:36,,
mRsOcOLTlc,mJGNX5nAmo,uK3RXUJ0V,,新浪微博,0,!!!!!!!!!@uK3RXUYW3: //@u0AGMTTVD: !!!!!!!!,,2012-01-03 01:17:39,,
mZmwFtOdVX,mcyE5GR7GJ,uK3RXUJ0V,,新浪微博,0,想要><@uK3RXUYW3: //@ukn: 全都想要啊QAQ,,2012-01-03 01:12:55,,
mid,retweeted_status_mid,uid,retweeted_uid,source,image,text,geo,created_at,deleted_last_seen,permission_denied
我们按照微博的创建日期来排序。这里面的关键变量是k9
,表示我们是按照第9列字段,即created_at
来排序,‘ -t','
则表示列与列之间的分隔符是逗号。
head -n 5 week1.csv | sort -f -t',' -k9
求出:
mZmwFtOdVX,mcyE5GR7GJ,uK3RXUJ0V,,新浪微博,0,想要><@uK3RXUYW3: //@ukn: 全都想要啊QAQ,,2012-01-03 01:12:55,,
mH44qG6iUm,mH44qL9LlF,uK3RXUJ0V,,新浪微博,0,求一切順利!!!,,2012-01-03 01:15:36,,
mRsOcOLTlc,mJGNX5nAmo,uK3RXUJ0V,,新浪微博,0,!!!!!!!!!@uK3RXUYW3: //@u0AGMTTVD: !!!!!!!!,,2012-01-03 01:17:39,,
mCClUNCqwe,mU5j0dIAkQ,uK3RXUJ0V,,新浪微博,0,转发微博,,2012-01-03 02:02:27,,
mid,retweeted_status_mid,uid,retweeted_uid,source,image,text,geo,created_at,deleted_last_seen,permission_denied
甄选特定列:cut
在初步浏览到数据内容之后,明白规律了,我们可以只输出其中的第9列的创建日期created_at
与第3列的用户编号uid
。这里面的关键参数是f 3,9
,表示我们是按照第3、9列字段,即只要uid
与created_at
的内容。
head -n 5 week1.csv | cut -d, -f 3,9
求出的值如下:
uK3RXUJ0V,2012-01-03 02:02:27
uK3RXUJ0V,2012-01-03 01:17:39
uK3RXUJ0V,2012-01-03 01:15:36
uK3RXUJ0V,2012-01-03 01:12:55
过滤重复数据:uniq
我们还可以结合uniq
参数来指定过滤重复数据。现在,让我们提出前10条不重复记录中不重复的uid
,并且通过 -c
参数输出各自重复的次数。-c参数就是count
计次的缩写。
head -n 10 week1.csv | cut -d, -f 3 | uniq -c
求出结果如下:
1 uid
9 uK3RXUJ0V
我们想看看哪些记录重复了,使用-d参数,-d参数即英文单词 duplicated
的缩写:
head -n 10 week1.csv | cut -d, -f 3 | uniq -d
求出结果为:
uK3RXUJ0V
我们继续看看哪些没有重复:
head -n 10 week1.csv | cut -d, -f 3 | uniq -u
求出:
uid
因为前10条记录都是uid
编号为uK3RXUJ0V
这位用户发表的微博,因此,我们看到重复的都是它,唯一的则求不出结果。当我们将n从10条记录调整为100条记录,
敲入命令:
head -n 100 week1.csv | cut -d, -f 3 | uniq -c
则求出结果为:
1 uid
26 uK3RXUJ0V
1 uBK141SAB
7 uK3RXUJ0V
1 uP2ZKPZ20
1 uK3RXUJ0V
1 uP2ZKPZ20
2 uK3RXUJ0V
1 uONPETMOB
1 uK3RXUJ0V
1 uONPETMOB
1 uP2ZKZFAU
1 uK3RXUJ0V
1 uPKFL33HE
2 uONPETMOB
1 uPKFL33HE
2 uK3RXUJ0V
1 uPKFL33HE
1 uONPETMOB
1 uK3RXUJ0V
1 uPKFL33HE
1 uONPETMOB
1 uB5NOA2SS
1 uK3RXUJ0V
1 uB5NOA2SS
1 uTZ5BU1OH
1 uDSGGUNU
2 uPKFL33HE
1 uHRVNMSGA
1 uQSM0Y4RC
1 uII5DACZ0
1 uATZSQYEB
1 uRUCU2QA
1 uLMIKLFQC
1 uBIBFPOU4
1 uK3XFRYZD
1 uR1WWH1D0
1 uWWBHASRW
1 uQHC0PYVV
1 uEMBAKNFB
1 uLCMDYZ2D
1 uONPER5VQ
1 uAHFO1MKZ
1 uS5WVAYPQ
1 uLCMYIJG1
1 uWWBWTFI3
1 uFAODMM1
1 uB4HTUV5U
1 uPKFT5MXC
1 uTS2TUD2R
1 uOQZQXY00
1 uDSCT0JP
1 uRLOGXFTI
1 uHQY4ALNQ
1 u0VPP3JTJ
1 u3511UIRE
1 uMMSWZPRC
1 uM1U5HNI5
1 uK3RXUJ0V
1 uK3RUZW1B
1 uK3RXUJ0V
1 uK3RUZW1B
1 uK3RXUJ0V
2 uK3RUZW1B
我们可以发现,前100条微博基本是uK3RXUJ0V
与uK3RXUJ0V
为核心,一个典型的星形社会网络结构。
查找:grep
既然uK3RXUJ0V
与uK3RXUJ0V
两人在社交媒体上发微博这么勤快,我们使用grep命令查找处他们俩更多秘密。
先找出uK3RXUJ0V
的所有发过的微博数量。
cat week1.csv | grep uK3RXUJ0V | cut -d, -f 3 | uniq -c
求出:
189 uK3RXUJ0V
1 uK3RXUYW3
55 uK3RXUJ0V
5 uK3RXUYW3
我们发现,uK3RXUJ0V
这哥们在数据集中出现了189+55次,可能是发了这么多条微博。
粘贴数据:paste
在本数据包中,我们有近50g数据,其中,由很多个平均不到1g的数据小文件构成,怎么将他们合并为一个大文件?
paste week2.csv week3.csv > snadata
我们也可以一口气合并50g文件。。。。但是,一般的电脑内存够吗?
paste week*.csv> snadata
更多命令敬请参考:paste (Unix) - Wikipedia, the free encyclopedia
导出文件: >
接下来,我们看看这哥们一般在什么时候发微博。我们将求出的结果直接另存为一个csv文件,以便于下一步可视化。
cat week1.csv | grep uK3RXUJ0V | cut -d, -f 9 | uniq -c > uK3RXUJ0V.csv
稍等几秒,数据保存成功。我们看到文件夹目录下面多了个uK3RXUJ0V.csv
文件。
我们使用最早学到的head
命令查看前5行:
cat uK3RXUJ0V.csv | head -n 5
求出结果为:
1 2012-01-03 02:02:27
1 2012-01-03 01:17:39
1 2012-01-03 01:15:36
1 2012-01-03 01:12:55
1 2012-01-03 01:10:42
利器:awk
利器awk非常强大,在此,我们仅仅用到它一个小小的功能,作为描述大数据及摘要信息的一个小示范。
cat week1.csv | awk -F "," '{ sum += $3 } END { printf "%.2f\n", sum }'
求出:
4024.00
这里的重要参数是,-F
表示csv的分割符,$3
表示我们以逗号分割的第三列的内容,然后通过awk的printf
函数与sum
函数,逐行求出并汇总。
参考
- Unix Toolbox
- An Introduction to the Unix Shell
- AWK - 维基百科,自由的百科全书
-
[Data Analysis with the Unix Shell comSysto Blog](http://blog.comsysto.com/2013/04/25/data-analysis-with-the-unix-shell/) - Dr. Bunsen / Explorations in Unix
- 有用的数据科学Unix命令
- dataists » A Taxonomy of Data Science
- » Intro to the Linux Command Line hilarymason.com