4번째와 다음 열에서 awk olny를 사용하여 일부 데이터를 평활화하는 데 도움이 필요합니다. 다음은 데이터 예입니다.
Date;time;Time_ms;A;B;C;D
23.11.2012;15:03:00;41236627696;1;2;2;3
23.11.2012;15:04:00;41236628391;2;3;3;11
23.11.2012;15:06:00;41236629097;1;23;7;15
24.11.2012;15:07:00;41236627696;1;4;5;3
24.11.2012;15:08:00;41236628391;3;12;1;2
24.11.2012;15:09:00;41236629097;2;23;71;15;8
23.11.2012;15:10:00;41236627696;7;1;2;2;3
23.11.2012;15:11:00;41236628391;2;3;12;1;
23.11.2012;15:12:00;41236629097;22;2;7;15
출력은 Date;time;Time_ms를 수정해서는 안 되며 처음 n 행에 대한 A 필드와 다음 n 행에 대한 A 필드를 포함하는 A의 평균을 인쇄해서는 안 됩니다. B, C, D열도 같은 작업을 수행해야 합니다. 예를 들어 n=1인 경우 두 번째 줄은 다음과 같습니다.
23.11.2012;15:04:00;41236628391;(1+2+1)/3;(2+3+23)/3;(2+3+7)/3;(3+11+15)/3
어쩌면 이런 것이 출발점이 될 수도 있겠네요
BEGIN { WIDTH=3 }
{ DATA[(++N)%WIDTH]=$0 }
(N>=WIDTH) {
V=0
for(X=(N+1); X<=(N+WIDTH); X++)
V+=DATA[X%WIDTH];
print V/WIDTH;
}
답변1
통계자료 처리를 위해,오른쪽일반적으로 사용하기가 더 쉽습니다.
모든 데이터를 메모리로 읽는 것이 더 쉬울 것입니다. Awk는 최고의 언어는 아닙니다(물론 가능하긴 하지만). 이것은 빠른 Python 스크립트입니다.
#!/usr/bin/env python
import sys
n = int(sys.argv[1]) # the smooth parameter n must be passed as the first argument to the script
print sys.stdin.readline() # print the header line
def split_line(line): # split line into first 3 fields as string, then list of numbers
fields = line[:-1].split(";")
return [";".join(fields[:3])] + map(float, fields[3:7])
rows = map(split_line, sys.stdin.readlines())
def avg(i, j):
return (rows[i-n][j] + rows[i][j] + rows[i+n][j]) / 3
for i in xrange(n, len(rows) - n):
print ";".join([rows[i][0]] + [str(avg(i, j-2)) for j in xrange(3, 7)])
데이터가 정말 큰 경우 여기에 있는 스크립트가 그 효과를 발휘할 것이라고 생각합니다. 2*n+1 행을 읽어서 그 값을 plus 에 저장하고 prev[2*n]
(n+1) 행의 평균을 출력합니다.prev[1]
$0
awk -F ';' -v OFS=';' -v n="${1-1}" '
function avg(i) { return (prev[2*n, i] + prev[n, i] + $i) / 3; }
NR == 1 { print; next } # title line: print and skip the rest
NR >= 2*n+2 {
# fourth line on: print the average values from the past 3 lines
# with the labels from the previous line
print labels[n], avg(4), avg(5), avg(6), avg(7);
}
{
# shift the saved averages by 1 position
for (i=4; i<=7; i++) {
for (k=2*n; k>1; k--) prev[k, i] = prev[k-1, i];
prev[1, i] = $i;
}
# save the labels of this line to print in the next round
for (k=n; k>1; k--) labels[k] = labels[k-1];
labels[1] = $1 ";" $2 ";" $3;
}
'
답변2
알게 된 후 작성한 스크립트입니다.이것
#!/usr/bin/bash
awk 'BEGIN { FS=OFS=";"
RS="\n"}
{
gsub(/\n/,"",$0)
if (max_nf<NF)
max_nf=NF
max_nr=NR
for(x=1; x<=NF; ++x)
vector[NR,x]=$x
}
END {
row=1
printf vector[row,1] OFS vector[row,2] OFS vector[row,3]
for(col=4; col<max_nf; ++col)
printf OFS "Average(" vector[row,col] ")";
printf ORS
for(row=2; row<max_nr; ++row) {
printf vector[row,1] OFS vector[row,2] OFS vector[row,3]
for(col=4; col<max_nf; ++col)
printf OFS (vector[row,col]+vector[row-1,col]+vector[row+1,col])/3 ;
printf ORS
}
}' File_IN.csv>File_OUT.csv
스크립트는 csv 파일을 2D 배열로 저장한 다음 첫 번째 줄을 인쇄합니다. 열 > 4의 경우 평균(제목)을 인쇄합니다. 두 번째 줄부터 파일 끝까지 첫 번째, 두 번째, 세 번째 열과 4보다 큰 열의 평균을 인쇄합니다. @gilles의 Python 스크립트가 제대로 작동하더라도 요청한 대로 AWK를 사용하기 때문에 이 스크립트를 답변으로 선택합니다.