Найти длительности и их среднее значение между наборами данных в интервале в сценарии оболочки - PullRequest
1 голос
/ 07 января 2020

Это связано с моим старым вопросом Найдите длительности и их максимум между наборами данных в интервале в сценарии оболочки

У меня есть набор данных как:

ifile.txt
2
3
2
3
2
20
2
0
2
0
0
2
1
2
5
6
7
0
3
0
3
4
5

Я хотел бы выяснить различную длительность и их среднее значение между 0 значениями в интервале 6 значений.

Вывод моего желания:

ofile.txt
6 5.33
1 2
1 2
1 2
5 4.2
1 3
3 4

Где

6 is the number of counts until next 0 within 6 values (i.e. 2,3,2,3,2,20) and 5.33 is the average value among them;
1 is the number of counts until next 0 within next 6 values (i.e. 2,0,2,0,0,2) and 2 is the average;
Next 1 and 2 are within same 6 values;
5 is the number of counts until next 0 within next 6 values (i.e. 1,2,5,6,7,0) and 4.2 is the average among them;
And so on

Согласно ответу на мой предыдущий вопрос, я пытался с этим:

    awk '
$0!=0{
  count++
  sum=sum+$0
  found=""
}
$0==0{
  print count,max
  count=max=0
  next
}
FNR%6==0{
  print count,max
  count=max=0
  found=1
}
END{
  if(!found){
      print count,max
  }
}
'  Input_file | awk '!/^ /' | awk '$1 != 0'

Ответы [ 2 ]

4 голосов
/ 07 января 2020

РЕДАКТИРОВАТЬ3: Еще одна попытка, поскольку 2-й набор из 6 строк имеет 2 0 2 0 0 2, поэтому его вывод должен быть 1 2, 1 2, 0 0,1 2, если это так (что, я считаю, в идеале должно быть ), затем попробуйте выполнить следующее.

awk '
{
  occur++
}
{
  count=$0!=0?++count:count
  sum+=$0
}
$0==0 || occur==6{
  printf("%d %0.2f\n",count,count?sum/count:prev)
  prev=count?sum/count:0
  prev_count=count
  count=sum=prev=prev_count=""
  if(occur==6){
    occur=""
  }
}
END{
  if(occur){
      printf("%d %0.2f\n",count?count:prev_count,count?sum/count:prev)
  }
}
'  Input_file | awk '$1 != 0'

Вывод будет следующим:

6 5.33
1 2.00
1 2.00
1 2.00
5 4.20
1 3.00
3 4.00


РЕДАКТИРОВАТЬ, приведенные ниже, могут помочь в подобных проблемах которые немного отличаются от этой актуальной проблемы, поэтому держите их здесь в посте.

EDIT2: В случае, если вы не хотите СБРОС СЧЕТА всякий раз, когда в Input_file встречается ноль, затем попробуйте следующее Это будет постоянно искать только 6 строк и НЕ будет сбрасывать счет.

awk '
{
  occur++
}
$0!=0{
  count++
  sum+=$0
  found=prev_count=prev=""
}
$0==0 && occur!=6{
  printf("%d,%0.2f\n",count?count:prev_count,count?sum/count:prev)
  prev=count?sum/count:0
  prev_count=count
  count=sum=""
  found=1
  next
}
occur==6{
  printf("%d,%0.2f\n",count,count?sum/count:prev)
  prev=count?sum/count:0
  prev_count=count
  count=sum=occur=""
  found=1
}
END{
  if(!found){
      printf("%d,%0.2f\n",count?count:prev_count,count?sum/count:prev)
  }
}
'  Input_file


РЕДАКТИРОВАТЬ1: Не могли бы вы попробовать следующее, протестировано и написано только с предоставленными образцами.

awk '
{
  occur++
}
$0!=0{
  count++
  sum+=$0
  found=prev_count=prev=""
}
$0==0{
  printf("%d,%0.2f\n",count?count:prev_count,count?sum/count:prev)
  prev=count?sum/count:0
  prev_count=count
  count=sum=occur=""
  found=1
  next
}
occur==6{
  printf("%d,%0.2f\n",count,count?sum/count:prev)
  prev=count?sum/count:0
  prev_count=count
  count=sum=occur=""
  found=1
}
END{
  if(!found){
      printf("%d,%0.2f\n",count?count:prev_count,count?sum/count:prev)
  }
}
'  Input_file

О чем заботится код:

  • Он заботится о логи c, где, если любые непрерывные 2 строки имеют значение 0, тогда будут напечатаны предыдущие счетные и средние значения для этой строки.
  • Это также позаботится о крайних случаях, таких как:

    a- Если строка НЕ ​​заканчивается 0, она проверит, есть ли какие-либо значения для печати с помощью созданного мной found флага.

    b- В случае последнего входного_файла строка НЕ ​​делится на 6, тогда и этот случай будет охватываться логикой END блока c проверки ее флагом found.

Объяснение: Добавление подробного пояснения к приведенному выше коду.

awk '                                                                      ##Starting awk program from here.
{
  occur++
}
$0!=0{                                                                     ##Checking condition if a line is NOT having zero value then do following.
  count++                                                                  ##Increment variable count with 1 each time it comes here.
  sum+=$0                                                                  ##Creating variable sum and keep adding current line value in it.
  found=prev_count=prev=""                                                 ##Nullifying variables found, prev_count, prev here.
}                                                                          ##Closing BLOCK for condition $0!=0 here.
$0==0{                                                                     ##Checking condition if a line is having value zero then do following.
  printf("%d,%0.2f\n",count?count:prev_count,count?sum/count:prev)         ##Printing count and count/sum here, making sure later is NOT getting divided by 0 too.
  prev=count?sum/count:0                                                   ##Creating variable prev which will be sum/count or zero in case count variable is NULL.
  prev_count=count                                                         ##Creating variable prev_count whose value is count.
  count=sum=occur=""                                                       ##Nullify variables count and sum here.
  found=1                                                                  ##Setting value 1 to variable found here.
  next                                                                     ##next will skip all further statements from here.
}                                                                          ##Closing BLOCK for condition $0==0 here.
occur==6{                                                                  ##Checking if current line is fully divided with 6 then do following.
  printf("%d,%0.2f\n",count,count?sum/count:prev)                          ##Printing count and count/sum here, making sure later is NOT getting divided by 0 too.
  prev=count?sum/count:0                                                   ##Creating variable prev which will be sum/count or zero in case count variable is NULL.
  prev_count=count                                                         ##Creating variable prev_count whose value is count.
  count=sum=occur=""                                                       ##Nullifying variables count and sum here.
  found=1                                                                  ##Setting value 1 to variable found here.
}                                                                          ##Closing BLOCK for condition FNR%6==0 here.
END{                                                                       ##Starting END block for this awk program here.
  if(!found){                                                              ##Checking condition if variable found is NULL then do following.
      printf("%d,%0.2f\n",count?count:prev_count,count?sum/count:prev)     ##Printing count and count/sum here, making sure later is NOT getting divided by 0 too.
  }
}
'  Input_file                                                                ##Mentioning Input_file name here.
1 голос
/ 07 января 2020

Другой, который не получился достаточно однострочным, на который я рассчитывал:

$ tail -n +2 file |        # strip header with tail to not disturb NR
awk ' 
{ 
    s+=$0                  # sum them up
    c++                    # keep count
}
$0==0 || NR%6==0 {         # act if zero or every 6th record
    if($0==0)              # remove zero effect on c
        c--
    if(s>0)                # avoid division by zero
        print c,s/c        # output
    s=c=0                  # rinse and repeat
}
END {                      # the end-game if NR%6!=0
    if($0==0)
        c--
    if(s>0)
        print c,s/c
}' 

Вывод:

6 5.33333
1 2
1 2
1 2
5 4.2
1 3
3 4

tail удаляет заголовок в файле до подачи данных в awk идея заключается в том, что заголовок не будет отображаться в NR. Если у вас нет заголовка, просто awk ... file.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...