我需要做多次求和;我的输入文件是:
DATE|NATION|CITY|FILES|REVENUE|FREQUENCY|INVESTMENT
20170807|USA|VIRGINIA|TIMES|1919150|1779|282075
20170807|USA|NYC|ROADS|92877|41|1599
20170808|USA|PENS|ROADS|133001|7|1
20170808|USA|NYC|TIMES|361625|1592|0
- 每 1 美元的 uniq 中总和 5 美元(日期)
- 在每个 uniq 中求和 $5,其中 $4=="TIMES"
- 每个 uniq 中的总和为 $5,其中 $4=="ROADS"
- 每个 uniq 中的总和为 $5,其中 $4=="ROADS" 和 $3=="NYC"
- 根据第$1列排列
我的预期输出
DATE|REV|TIMES|ROADS|ROADS&NYC
20170807|2012027|1919150|92877|92877
20170808|494626|361625|133001|0
我只知道如何根据 1 列求和
awk -F"|" '{FS=OFS="|"}{col[$1]+=$5} END {for (i in col) print i, col[i]}'
答案1
这是awk
解决方案:
awk -F'[|]' 'NR>1 { I[$1]+=$5 }
($4=="TIMES") { T[$1]+=$5 }
($4=="ROADS") { R[$1]+=$5 }
($4=="ROADS" && $3=="NYC"){ RN[$1]+=$5 }
END{ print "DATE|REV|TIMES|ROADS|ROADS&NYC"
for (x in I) printf"%d|%d|%d|%d|%d\n", x, I[x], T[x], R[x], RN[x]
}' infile.txt
答案2
复杂的呆呆地达到目标的解决方案:
awk 'BEGIN{ FS=OFS="|" }NR==1{ next }{ sum[$1]+=$5 }
$4=="TIMES"{ d[$1]["t"]+=$5 }
$4=="ROADS"{ d[$1]["r"]+=$5 }$3=="NYC" && $4=="ROADS"{ d[$1]["r&n"]+=$5 }
END{ print "DATE|REV|TIMES|ROADS|ROADS&NYC";
for(i in d) print i, sum[i], int(d[i]["t"]), int(d[i]["r"]), int(d[i]["r&n"]) }' file
输出:
DATE|REV|TIMES|ROADS|ROADS&NYC
20170807|2012027|1919150|92877|92877
20170808|494626|361625|133001|0
答案3
您不需要多个数组。只需在字段上编写索引,对所有内容求和并仅返回所需的求和索引,添加 0 以确保NULL
显示字段。
awk 'BEGIN{FS=OFS="|"; print "DATE|REV|TIMES|ROADS|ROADS&NYC"}
NR>1{rev[$1]+=$5; sum[$1$4]+=$5; sum[$1$4$3]+=$5}
END{for (dt in rev) print dt, rev[dt], sum[dt"TIMES"]+0, sum[dt"ROADS"]+0, sum[dt"ROADSNYC"]+0}' file
它也更具可读性......
答案4
使用磨坊主( mlr
):
mlr --csv --fs pipe \
reshape -s FILES,REVENUE then \
put '$tmp=$ROADS; $REV=$ROADS+$TIMES' then \
reshape -s CITY,tmp then \
stats1 -a sum -g DATE -f REV,TIMES,ROADS,NYC then \
unsparsify --fill-with 0 file.csv
给定问题中的数据,这会生成以下内容:
DATE|REV_sum|TIMES_sum|ROADS_sum|NYC_sum
20170807|2012027|1919150|92877|92877
20170808|494626|361625|133001|0
第一个操作(reshape
操作)从字段中获取值FILES
,并使用来自 的值从这些字段生成新字段REVENUE
。这为我们提供了以下记录(在三个单独的集合中,因为某些记录缺少某些字段):
日期 | 国家 | 城市 | 频率 | 投资 | 时代 |
---|---|---|---|---|---|
20170807 | 美国 | 弗吉尼亚州 | 第1779章 | 282075 | 1919150 |
日期 | 国家 | 城市 | 频率 | 投资 | 道路 |
---|---|---|---|---|---|
20170807 | 美国 | 纽约市 | 41 | 1599 | 92877 |
20170808 | 美国 | 笔 | 7 | 1 | 133001 |
日期 | 国家 | 城市 | 频率 | 投资 | 时代 |
---|---|---|---|---|---|
20170808 | 美国 | 纽约市 | 第1592章 | 0 | 361625 |
该put
操作通过对和值REV
求和来计算每条记录的字段(每条记录中将缺少其中一个)。我们还计算一个临时值,稍后将用于计算 的收入总和。之后,我们有以下数据:ROADS
TIMES
ROADS
NYC
put
日期 | 国家 | 城市 | 频率 | 投资 | 时代 | 转速 |
---|---|---|---|---|---|---|
20170807 | 美国 | 弗吉尼亚州 | 第1779章 | 282075 | 1919150 | 1919150 |
日期 | 国家 | 城市 | 频率 | 投资 | 道路 | tmp | 转速 |
---|---|---|---|---|---|---|---|
20170807 | 美国 | 纽约市 | 41 | 1599 | 92877 | 92877 | 92877 |
20170808 | 美国 | 笔 | 7 | 1 | 133001 | 133001 | 133001 |
日期 | 国家 | 城市 | 频率 | 投资 | 时代 | 转速 |
---|---|---|---|---|---|---|
20170808 | 美国 | 纽约市 | 第1592章 | 0 | 361625 | 361625 |
第二个reshape
为我们提供了一种更轻松地计算ROADS
总和的方法NYC
:
日期 | 国家 | 城市 | 频率 | 投资 | 时代 | 转速 |
---|---|---|---|---|---|---|
20170807 | 美国 | 弗吉尼亚州 | 第1779章 | 282075 | 1919150 | 1919150 |
20170808 | 美国 | 纽约市 | 第1592章 | 0 | 361625 | 361625 |
日期 | 国家 | 频率 | 投资 | 道路 | 转速 | 纽约市 |
---|---|---|---|---|---|---|
20170807 | 美国 | 41 | 1599 | 92877 | 92877 | 92877 |
日期 | 国家 | 频率 | 投资 | 道路 | 转速 | 笔 |
---|---|---|---|---|---|---|
20170808 | 美国 | 7 | 1 | 133001 | 133001 | 133001 |
然后我们使用该stats1
命令计算所需字段的总和,按以下方式分组DATE
:
日期 | 转速总和 | TIMES_sum | ROADS_sum | 纽约总和 |
---|---|---|---|---|
20170807 | 2012027 | 1919150 | 92877 | 92877 |
日期 | 转速总和 | TIMES_sum | ROADS_sum |
---|---|---|---|
20170808 | 494626 | 361625 | 133001 |
然后我们最终对其进行稀疏化,以便所有缺少其他记录中存在的字段的记录都在这些字段中添加零作为值:
日期 | 转速总和 | TIMES_sum | ROADS_sum | 纽约总和 |
---|---|---|---|---|
20170807 | 2012027 | 1919150 | 92877 | 92877 |
20170808 | 494626 | 361625 | 133001 | 0 |