众所周知,awk、sed是相对高阶的Linux命令,是处理数据的神兵利器。另外awk不仅仅是一个命令,它本身的语法也是一门编程语言。
学习awk有时候倒不是有多难,只是各种细节,经常忘,每次用起来的时候又要重新在浩瀚的互联网上搜索一番。着实费力,本文用一些实战演练来帮你学习awk,建议收藏。用的时候可以速查一下。
数据集
首先为了方便演练,我们需要一个公开的数据集,可以去这个网站:https://grouplens.org/datasets/movielens/ 寻找电影评分相关的数据。
你也可以直接复制如下链接,来直接数据集的压缩包。https://files.grouplens.org/datasets/movielens/ml-25m.zip
rating.csv
rating.csv数据集中一个csv文件,记录了用户给电影评分相关的数据,它有4列,如下:
userId,movieId,rating,timestamp 1,296,5.0,1147880044 1,306,3.5,1147868817 1,307,5.0,1147868828 1,665,5.0,1147878820 1,899,3.5,1147868510 1,1088,4.0,1147868495 1,1175,3.5,1147868826 1,1217,3.5,1147878326 1,1237,5.0,1147868839
首先可以预处理去掉第一行(列名)
sed -i '1d' ratings.csv
聚合
计算总评分
awk -F ',' '{sum += $3} END {print sum}' ratings.csv
awk的列序号是从1计数的,因为0表示这一整行。评分(rating)是第三列,所以加$3
。
计算平均分
awk -F ',' '{sum += $3} END {print sum/NR}' ratings.csv
统计每个用户给多少部电影评过分
awk -F',' '{x[$1]++} END{for (i in x) printf("%s,%s\n", i,x[i])}' ratings.csv
awk -F',' '{x[$1]++} END{for (i in x) print i","x[i]}' ratings.csv
print i","x[i]
可以替换成 printf("%s,%s\n", i, x[i])
计算每个用户评分的平均分
awk -F',' '{x[$1]++; y[$1]+=$3} END{for (i in x) print i","y[i]/x[i]}' ratings.csv
生成每个用户打过分的电影列表
userId后面使用: movId之间用,
awk -F',' '{x[$1][$2]=0} END{for(i in x) {printf("%s:",i); for(j in x[i]) printf("%s,",j); print ""}}' ratings.csv
107845:25,32,36,62,95,112,141,260,494,608,628,637,648,653,733,736,762,786,788,802,
上面这个语法用到了awk的二维数组,有些awk的命令可能不支持(比如Mac上的awk),还可以这样写:
awk -F',' '{x[$1] = x[$1]""$2","} END {for (i in x) print i":"x[i]}' ratings.csv
字符串的拼接不用直接用+,不然会按数字处理。字符串的拼接用a = a""b
。
如果想去掉末尾的逗号。
awk -F',' '{if (x[$1] != "") x[$1] = x[$1]","$2; else x[$1] = ""$2;} END {for (i in x) print i":"x[i]}' ratings.csv
生成每个用户打过分的电影列表含评分
格式如下:
userid:movId,rating;movid,rating;
awk -F',' '{x[$1] = x[$1]""$2","$3";"} END {for (i in x) print i":"x[i]}' ratings.csv
可以将上面生成的文件保存成new_rating.csv。继续用来演示数据拆分
拆分
把new_rating拆分成单行
格式如下:
userId,movId,rating
awk -F'[:;]' '{for(i = 2; i < NF; i++) print $1","$i}' new_rating.csv
133419,81562,3.0 133419,96488,4.0 133419,5952,3.5 133419,34405,3.5 133419,6187,3.5 133419,4226,4.0 133419,33166,4.5 133419,3977,3.0 133419,6539,4.0 133419,3897,4.0
把new_rating拆分成单行
同时修改分隔符为TAB
userId\t
movId\t
rating
两次分割实现:
awk -F'[:;]' '{for(i = 2; i < NF; i++) {split($i, x, ","); print $1"\t"x[1]"\t"x[2] }}' new_rating.csv
一次分割实现
awk -F'[:;,]' '{for(i = 2; i < NF; i+=2) print $1"\t"$i"\t"$(i+1)}' new_rating.csv
关联
将电影ID替换成电影名
我们的数据集中还有一个文件是 movies.csv,里面有电影的信息:
movieId,title,genres 1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fan>tasy 2,Jumanji (1995),Adventure|Children|Fantasy 3,Grumpier Old Men (1995),Comedy|Romance 4,Waiting to Exhale (1995),Comedy|Drama|Romance 5,Father of the Bride Part II (1995),Comedy 6,Heat (1995),Action|Crime|Thriller 7,Sabrina (1995),Comedy|Romance 8,Tom and Huck (1995),Adventure|Children 9,Sudden Death (1995),Action
这需要awk一次处理两个文件。
awk -F',' 'BEGIN {FS=","; while(getline<"movies.csv") a[$1]=$2} {$2=a[$2]; OFS=",";print $0}' ratings.csv
原文地址:https://cloud.tencent.com/developer/article/2171232
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。