对多列求和

对多列求和

我需要做多次求和;我的输入文件是:

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. 每 1 美元的 uniq 中总和 5 美元(日期)
  2. 在每个 uniq 中求和 $5,其中 $4=="TIMES"
  3. 每个 uniq 中的总和为 $5,其中 $4=="ROADS"
  4. 每个 uniq 中的总和为 $5,其中 $4=="ROADS" 和 $3=="NYC"
  5. 根据第$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求和来计算每条记录的字段(每条记录中将缺少其中一个)。我们还计算一个临时值,稍后将用于计算 的收入总和。之后,我们有以下数据:ROADSTIMESROADSNYCput

日期 国家 城市 频率 投资 时代 转速
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

相关内容