基于分钟的列总和

时间:2014-11-17 10:28:15

标签: shell unix awk

以下是我的输入文件:

  • 第1列是时段和分钟的组合
  • 第二列是计数

数据是分钟的。

我需要通过对每个分钟块进行求和来将数据转换为分钟数,即[1-5,6-10等]。我需要这些数据在jfree图表中绘制。请建议如何获得输出

输入:

11.01:5
11.02:4
11.03:3
11.04:8
11.05:2
12.11:3
12.12:4
12.13:1
12.15:0
13.03:04
22.56:01
22.57:03
22.58:2
23.00:0

输出:

11.05:22
12.15:8
13.05:4
23.00:6

4 个答案:

答案 0 :(得分:1)

这个awk应该可以工作:

awk -F '[.:,]' -v OFS=: '{
   p=5*int(($2+4)/5);
   $1=1*$1;
   if(p==60){
      p="0";
      $1++
   }
   k=sprintf("%02d.%02d", $1, p)
}
!s[k]{
   b[++n]=k
}
{
   s[k]+=$3
}
END{
   for (i=1; i<=n; i++)
      print b[i],s[b[i]]
}' file
11.05:22
12.15:8
13.05:4
23.00:6

答案 1 :(得分:1)

这是草稿。一旦你展示了一些尝试,我将提供更通用的方法:

awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; a[$1"."r]+=$3} END {for (i in a) print i, a[i]}' file

对于您的给定输入,它返回:

22.60:6
13.5:4
12.15:8
23.5:0
11.5:22

关键是要将每1,2,3,4和5映射到5.我这样说:

d -> d-1 -> (d-1)/5 (int division) -> (d-1)/5 * 5

要确保没有出现分钟60,您可以添加一些条件:if (r==60) {r=0; $1++}

$ awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; if (r==60) {r=0; $1++}; a[$1"."r]+=$3} END {for (i in a) print i, a[i]}' file
23.0:6
13.5:4
12.15:8
23.5:0
11.5:22

你也可以做一些奇特的事情,比如打印领先的0几分钟&lt; 10,然后打印那些总和为&gt; 0的值:

$ awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; if (r==60) {r=0; $1++}; r=sprintf("%02d", r); a[$1"."r]+=$3} END {for (i in a) if (a[i]) print i, a[i]}' file
11.05:22
12.15:8
13.05:4
23.00:6

答案 2 :(得分:0)

这个问题可以通过百万种不同的方式解决:sed,awk,python等。

以下是使用常见bash命令执行此操作的方法。

#!/bin/bash

# extract the unique set of hours from the input (i.e. 11, 12, 13, 22, 23)
#
hours=$(cut -f 1 -d . test.txt | sort -u)
for hour in $hours; do

    # initialize sum for this hour
    #
    count=0

    # extract the number following the ':'
    #
    for x in $(grep "^$hour" test.txt | cut -f 2 -d :); do
        # sum up the numbers following the ':'
        #
        count=$(($count + $x))
    done

    # Extract the last timestamp for the given hour
    #
    t=$(grep "^$hour" test.txt | tail -1  | cut -f 1 -d :)

    # Print the desired output of timestamp:sum
    #
    echo $t:$count
done

这是输出:

11.05:22
12.15:8
13.03:4
22.58:6
23.00:0

您的输入存储在test.txt文件中:

11.01:5
11.02:4
11.03:3
11.04:8
11.05:2
12.11:3
12.12:4
12.13:1
12.15:0
13.03:04
22.56:01
22.57:03
22.58:2
23.00:0

让我指出你在脚本中看到的一些命令

  1. cut用于从输入中提取列。 cut -f 1 -d .将从您的输入中提取小时。 -f 1表示打印列1和-d .表示使用&#39;。&#39;作为分遣者。
  2. tail -f 1打印尾部输入的最后一行。
  3. sort -u从输入中删除重复行。

答案 3 :(得分:0)

再多一次awk

如果要舍入到最接近的5

awk -F"[.:]" '{$2=(t=($2%5))>2?$2-t+5:$2-t;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
              END{for(i in b)print i"."b[i]":"a[i]}' file

如果你想要整理不是5的倍数的所有内容。

awk -F"[.:]" '{$2=$2%5!=0?$2-($2%5)+5:$2;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
              END{for(i in b)print i"."b[i]":"a[i]}' file

圆形到最接近的5

的输出
11.5:22
12.15:8
22.55:4
13.5:4
23.0:2

向下舍入到下一个5

的倍数
11.05:22
12.15:8
13.5:4
23.00:6

正如你在输出中看到的那样,它将四舍五入到最接近的5,这就是22.55存在的原因

舍入如何工作

当数字除以另一个

时,模数给出余数

24/5 = 4 remainder 4

所以

24%5 = 4

因此,要将数字向下舍入到X的下一个倍数,我们只需要减去余数,这样

N-(N%X) 24-(24%5)

始终是X的倍数(向下舍入)。

为了向上舍入,我们简单地说模数的结果是否超过X的一半(在这种情况下为5),然后将X添加到结果中以舍入到X的下一个倍数

(N-(N%X))+X (24-(24%5))+5

不确定这是否是最佳的圆形方式,但它有效:)