数据处理常用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列字段,即只要uidcreated_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条微博基本是uK3RXUJ0VuK3RXUJ0V为核心,一个典型的星形社会网络结构。

查找:grep

既然uK3RXUJ0VuK3RXUJ0V两人在社交媒体上发微博这么勤快,我们使用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函数,逐行求出并汇总。

参考

最新的: