我尝试使用 awk 脚本为每个商店创建销售报告。数据集为csv格式,有45个商店。数据示例如下:
Store,Store_name,Date,Year,Weekly_Sales,Holiday_Flag,Temperature,Fuel_Price,CPI,Unemployment
1,Store1,05-02-2010,2010,1643690.9,No,42.31,2.572,211.0963582,8.106
1,Store1,12-02-2010,2010,1641957.44,Yes,38.51,2.548,211.2421698,8.106
...
...
45,Store45,12-10-2012,2012,734464.36,No,54.47,4,192.3272654,8.667
45,Store45,19-10-2012,2012,718125.53,No,56.47,3.969,192.3308542,8.667
我正在尝试使用以下代码对商店进行分组并汇总各个组记录:
#!/usr/bin/awk -f
awk BEGIN {F=","} {a[$2]+=$5;}END{for(i in a)print i", "a[i];}
上面代码的输出如下:
Store1, 2.22403e+08
...
...
Store45, 1.12395e+08
我想要两件事:按降序排序,并更改不以科学记数法表示的数字并使用两个浮点。有人可以给我一些建议吗?
答案1
使用 printf 格式化输出。例如printf "%s, %.2f\n", i, a[i]
。并通过管道输入sort
对输出进行排序。例如:
按商店名称排序,使用 GNU 排序-V
选项进行“版本”排序(也称为“自然排序”):
$ awk -F, '{a[$2]+=$5;}END{for(i in a)printf "%s, %.2f\n", i, a[i]}' file.csv | sort -V -k1,1
Store1, 3285648.34
Store45, 1452589.89
按总销售额排序:
$ awk -F, '{a[$2]+=$5;}END{for(i in a)printf "%s, %.2f\n", i, a[i]}' file.csv | sort -k2,2
Store45, 1452589.89
Store1, 3285648.34
答案2
使用for (i in a)
循环会打乱输出索引的顺序a
,请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Scanning-an-Array。有更好的方法可以做到这一点,但由于您的商店已经在输入中排序,因此您根本不需要数组,只需一次处理一个商店即可在输出中以相同的方式保持商店排序。重新读取,这也更有内存和执行速度效率,因为您不需要将所有数据存储在内存中,然后循环遍历 END 部分中的所有存储。
$ cat tst.awk
BEGIN {
FS = ","
ofmt = "%s, %0.2f\n"
}
$2 != store {
if ( NR > 2 ) {
printf ofmt, store, tot
}
store = $2
tot = 0
}
{ tot += $5 }
END {
printf ofmt, store, tot
}
$ awk -f tst.awk file
Store1, 3285648.34
Store45, 1452589.89