#arrays #awk #interpolation
#массивы #awk #интерполяция
Вопрос:
мы хотели бы интерполировать данные внутри массива, используя ‘awk’. У меня есть массив
1 1 3 3 ...
3 3 5 3
5 5 6 5
6 6 6 5
для которого мы хотели бы получить
1 1 3 3 ...
2 2 4 4
3 3 5 3
4 4 5.5 4
5 5 6 5
6 6 6 5
Это позволило бы нам получить полный массив, охватывающий все возможные данные для первого столбца, представляющий временную шкалу. Столбец 2 и более — это данные. Матрица имеет размер 4×110100. У нас есть этот скрипт:
awk '
{
P[$1]=$2
I[i ]=$1
}
END{
j=0; s=I[j]; t=I[j 1]
for(i=m;i<=n;i ){
if(I[j 2] amp;amp; i>t){
j ; s=I[j]; t=I[j 1]
}
print i,P[s] (i-s)*(P[t]-P[s])/(t-s)
}
}' m=1 n=6 f1.dat > f2.dat
но это делается только для первых двух столбцов как
1 1
2 2
3 3
4 4
5 5
6 6
Как мы могли бы распространить интерполяцию на весь массив?! Я пробовал использовать скрипты ‘for’ или ‘while’, но мы не можем достичь цели…
Комментарии:
1. Почему вторая выходная запись
2 2 4 4
, а не2 2 4 3
?2. Упс… вы правы!
Ответ №1:
Вы можете сделать это, отслеживая только текущую и предыдущие строки:
BEGIN {
# initialise "previous" line
getline;
for (i=0; i<=NF; i ) p[i] = $i;
}
{
# print previous line
print p[0];
# check if column 1 has skipped
if ( (d = $1-p[1]) > 1 ) {
# if so, insert (d-1) new rows
for (i=1; i<d; i ) {
# interpolate values for each column
for (c=1; c<=NF; c ) {
printf "%s%s",
p[c] (i/d)*($c-p[c]), # linear interpolation
c==NF ? ORS : OFS; # avoid trailing spaces
}
}
}
# update previous line
for (i=0; i<=NF; i ) p[i] = $i;
}
END {
# print the final line
print p[0];
}