Как интерполировать массив в ‘awk’?

#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];
}