Как рассчитать среднее значение 2-го поля из файлов?

У меня есть файл, он состоит из двух полей. Формат первого поля - "%FT%T".

Пример данных:

2019-01-01T00:00:00  4.8
2019-01-01T01:00:00  5.1
2019-01-01T02:00:00  5.4
2019-01-01T03:00:00  5.7
2019-01-01T04:00:00  5.8
2019-01-01T05:00:00  5.4
2019-01-01T06:00:00  5
2019-01-01T07:00:00  4.4
2019-01-01T08:00:00  3.8
2019-01-01T09:00:00  3.7
2019-01-01T10:00:00  3.8
2019-01-01T11:00:00  4.1
2019-01-01T12:00:00  5
2019-01-01T13:00:00  6.7
2019-01-01T14:00:00  8.4
2019-01-01T15:00:00  9.1
2019-01-01T16:00:00  8.6
2019-01-01T17:00:00  8.5
2019-01-01T18:00:00  8.6
2019-01-01T19:00:00  8.1
2019-01-01T20:00:00  8
2019-01-01T21:00:00  6.9
2019-01-01T22:00:00  5.6
2019-01-01T23:00:00  5.2
2019-01-02T00:00:00  5.2
2019-01-02T01:00:00  5.3
2019-01-02T02:00:00  5.8
2019-01-02T03:00:00  6
2019-01-02T04:00:00  5.7
2019-01-02T05:00:00  5.4
2019-01-02T06:00:00  5.7
2019-01-02T07:00:00  5.3
2019-01-02T08:00:00  4.8
2019-01-02T09:00:00  4.3
2019-01-02T10:00:00  3.6
2019-01-02T11:00:00  2.8
2019-01-02T12:00:00  3.2
2019-01-02T13:00:00  4.2
2019-01-02T14:00:00  4.9
2019-01-02T15:00:00  5.4
2019-01-02T16:00:00  5.9
2019-01-02T17:00:00  6.5
2019-01-02T18:00:00  6.7
2019-01-02T19:00:00  7.1
2019-01-02T20:00:00  5.7
2019-01-02T21:00:00  4.4
2019-01-02T22:00:00  4.1
2019-01-02T23:00:00  3.8
2019-01-03T00:00:00  4
2019-01-03T01:00:00  3.5
2019-01-03T02:00:00  3.6
2019-01-03T03:00:00  4
2019-01-03T04:00:00  4.2
2019-01-03T05:00:00  3.9
2019-01-03T06:00:00  3.7
2019-01-03T07:00:00  3.8
2019-01-03T08:00:00  3.7
2019-01-03T09:00:00  3.7
2019-01-03T10:00:00  4
2019-01-03T11:00:00  4.7
2019-01-03T12:00:00  5.4
2019-01-03T13:00:00  6.5
2019-01-03T14:00:00  7.6
2019-01-03T15:00:00  7.7
2019-01-03T16:00:00  7.3
2019-01-03T17:00:00  7.4
2019-01-03T18:00:00  8
2019-01-03T19:00:00  8.5
2019-01-03T20:00:00  8.1
2019-01-03T21:00:00  6.5
2019-01-03T22:00:00  5.6
2019-01-03T23:00:00  5.6

Я хочу рассчитать среднесуточное значение 2-го столбца.

Результат должен быть следующим...

01-01-2019 6.1
02-01-2019 5.1
03-01-2019 5.5

2 ответа

Решение

Подход awk:

$ awk '{ 
    date=substr($1,1,10); 
    tot[date]+=$2; 
    num[date]++
    }
    END{
        for(date in tot){
            printf "%s %.1f\n", date,tot[date]/num[date]
        }
    }' file 
2019-01-01 6.1
2019-01-02 5.1
2019-01-03 5.5

Использование Миллера

$ mlr --nidx --repifs put '
    $1 = strftime(strptime($1,"%FT%T"),"%d-%m-%Y")
  ' then stats1 -a mean -f 2 -g 1 file
01-01-2019 6.070833
02-01-2019 5.075000
03-01-2019 5.458333

Форматирование результатов, по-видимому, является областью, в которой Миллеру несколько не хватает, поэтому, если вам это нужно, я предлагаю передать результаты через numfmt напр.

$ mlr --nidx --repifs put '
    $1 = strftime(strptime($1,"%FT%T"),"%d-%m-%Y")
  ' then stats1 -a mean -f 2 -g 1 file | numfmt --field=2 --format='%.1f'
01-01-2019      6.1
02-01-2019      5.1
03-01-2019      5.5

В качестве альтернативы, используя достаточно свежую версию GNU awk и используя mktime индексировать sum а также count массивы с эпохой даты:

gawk '
  {
    split($1,dt,"[-T:]");
    k = mktime(sprintf("%04d %02d %02d 00 00 00", dt[1], dt[2], dt[3]));
    sum[k] += $2; count[k] += 1;
  }
  END {
    PROCINFO["sorted_in"] = "@ind_num_asc";
    for(k in count) printf "%s %.1f\n", strftime("%d-%m-%Y",k), sum[k]/count[k];
  }
' file

Другая альтернатива с использованием csvsql/csvformat из Python на основе csvkit:

$ csvsql -d ' ' -HS --query '
    SELECT strftime("%d-%m-%Y",date(a)) AS [Day], round(avg(b),1) AS [Avg] FROM file GROUP BY date(a)
  ' file | csvformat -T
/usr/lib/python3/dist-packages/agate/table/from_csv.py:88: RuntimeWarning: Column names not specified. "('a', 'b')" will be used as names.
Day Avg
01-01-2019  6.1
02-01-2019  5.1
03-01-2019  5.5
Другие вопросы по тегам