예를 들어, 09:00:00 - 16:59:59 사이의 매초 형식의 파일이 있습니다.
[...]
10:59:49,76.77
10:59:50,38.78
10:59:51,23.23
10:59:52,12
10:59:53,26.47
10:59:54,10.2
10:59:55,32.67
10:59:56,14
10:59:57,42
10:59:58,100
10:59:59,100
[...]
데이터를 그래프로 작성하려고 하면 데이터가 너무 뭉쳐져 있어서 이해하기 힘들기 때문에 평균을 구해서 좀 더 아름답게 만들고 싶습니다.
예를 들어, 파일에서 10분마다 평균값을 어떻게 찾을 수 있습니까?
09:00:00 - 09:09:59
09:10:00 - 09:19:59
..
..
10:00:00 - 10:09:59
10:10:00 - 10:19:59
and so on...
나는 원래 평균을 찾기 위해 awk를 사용할 계획이었지만 이를 실행하기 위해 10분 클러스터를 추출하는 방법을 찾는 데 어려움을 겪고 있습니다.
awk -F "," '{ sum += $2; n++ } END { if (n > 0) print sum / n; }' test_file
테스트용 타임스탬프를 생성하려면 샘플 코드를 사용하세요.
#!/bin/bash
seq -f "%02g" 0 59 > tmp.sec
seq -f "%02g" 30 59 > tmp.firstmin
while read line
do
cat tmp.sec | sed "s/^/09:$line:/;s/$/,$RANDOM/"
done<"tmp.firstmin"
for i in `seq 10 15`
do
while read line
do
cat tmp.sec | sed "s/^/$i:$line:/;s/$/,$RANDOM/"
done<"tmp.sec"
done
답변1
구분 기호를 사용한 다음 초를 무시하고 분만 유지할 수 :
있습니다 ,
.
$ awk -F[:,] '{
thisInterval = substr($2,1,1);
a[$1":"thisInterval"0"]+=$4;
}
END{
PROCINFO["sorted_in"]="@ind_str_asc";
for(t in a){print t,a[t]/600
}
}'
위의 내용을 처리하려면 GNU awk가 필요 PROCINFO
하지만 나중에 언제든지 직접 재정렬할 수 있습니다. 또한 10분마다 600개의 데이터 포인트를 가정합니다.
답변2
암소 비슷한 일종의 영양awk
방법:
단순화된 예 testfile
:
09:00:00,1
09:03:00,3
09:09:59,6
10:00:00,1
10:02:49,76.77
10:03:50,38.78
10:05:51,23.23
10:07:52,12
10:09:53,26.47
10:09:59,10.2
10:59:55,32.67
10:59:56,14
10:59:57,42
10:59:58,100
10:59:59,100
awk -F',' 'BEGIN{ d = "9999 01 01 " }
{
gsub(":", " ", $1);
if (!ts) ts = mktime(d $1);
sum += $2; cnt += 1
}
cnt == 1 { next }
(mktime(d $1) - ts) == 599 {
print sum / cnt;
ts = sum = cnt = 0
}' testfile
산출:
3.33333
26.9214
답변3
타임스탬프에서 "0:00"을 일치시켜 새로운 10분 기간의 시작을 감지할 수 있습니다. 다음은 순수 bash의 예입니다. 정수 값만 처리하지만 평균을 계산하는 것은 어렵지 않으므로 이에 적응할 수 있습니다.
#!/bin/bash
SUM=0
while read line;
do
# search for "hh:m0:00"
if [ "${line:4:4}" = "0:00" ]
then
# reached new 10 minutes period
# get average from sum and save it
echo $((SUM/600)) >> results.txt
# reset sum
SUM=0
fi
# increment sum with this line value
SUM=$(($SUM+${line:9}))
done < input.txt
답변4
10분 = 600초이므로 600행마다 두 번째 필드의 합계를 계산하고 600행마다 도달하면 해당 값을 600으로 나누어 인쇄하기로 결정했습니다.
awk -F, '
NR % 600 == 1 {
start = $1
}
NR % 600 == 0 {
printf("%s - %s => %f\n", start, $1, avg / 600)
avg = 0
}
{
avg += $2
}
' input.txt
산출
09:00:00 - 09:09:59 => 49.807600
09:10:00 - 09:19:59 => 50.171900
09:20:00 - 09:29:59 => 47.775433
09:30:00 - 09:39:59 => 48.605350
09:40:00 - 09:49:59 => 49.591117
...
13:20:00 - 13:29:59 => 50.347733
13:30:00 - 13:39:59 => 50.321833
13:40:00 - 13:49:59 => 49.923333
13:50:00 - 13:59:59 => 48.644683
14:00:00 - 14:09:59 => 49.957433
...
16:00:00 - 16:09:59 => 50.333633
16:10:00 - 16:19:59 => 51.799317
16:20:00 - 16:29:59 => 50.931450
16:30:00 - 16:39:59 => 50.734167
16:40:00 - 16:49:59 => 49.857383
16:50:00 - 16:59:59 => 50.433733
를 생성하기 위해 input.txt
두 개의 프로그램을 만들었으며 원하는 것을 사용하십시오. 두 번째 프로그램이 더 빠릅니다.
첫 번째
date -f <(seq -f '@%g' 21600 50399) '+%H:%M:%S' |
awk '{
printf("%s,%.2f\n", $0, rand() * 100)
}'
두번째
awk '
BEGIN {
for(i = 9; i < 17; i++) {
for(j = 0; j < 60; j++) {
for(k = 0; k < 60; k++) {
printf("%02d:%02d:%02d,%.2f\n", i, j, k, rand() * 100)
}
}
}
}'