Как усреднить значения разных файлов и сохранить их в новом файле - PullRequest
0 голосов
/ 25 мая 2019

У меня есть около 140 файлов с данными, которые я хотел бы обработать с помощью скрипта.

Файлы имеют два типа имен:

  1. sys-time-4-16-80-15-1-1.txt

  2. known-ratio-4-16-80-15-1-1.txt

где два последних числа меняются.Предпоследнее число занимает 1, 50, 100, 150, ..., 300, а последнее число составляет 1,2,3,4,5 ..., 10.Пример этих файлов находится в этой ссылке .

Я хотел бы написать новый файл с 3 столбцами следующим образом:

A 1stстолбец с предпоследним номером файла, т. е. 1,25,50 ... 2-й столбец со средним значением второго столбца в каждом файле sys-time-...Третий столбец со средним значением второго столбца в каждом файле known-ratio-...

Результат может содержать строку для каждой пары усредненных 2nd columns из sys и known файлов:

1    mean-sys-1 mean-know-1
1    mean-sys-2 mean-know-2
.
.
1    mean-sys-10 mean-know-10
50   mean-sys-1  mean-know-1
50   mean-sys-2  mean-know-2
.
.
50   mean-sys-10 mean-know-10
100  mean-sys-1  mean-know-1
100  mean-sys-2  mean-know-2
.
.
100  mean-sys-10 mean-know-10
....
....
300  mean-sys-10 mean-know-10

, где каждая строка соответствует файлам sys и known с теми же двумя последними числами.Кроме того, я хотел бы скопировать в первый столбец предпоследнее число файлов.

Я знаю, как вычислить среднее значение второго столбца файла с помощью awk:

awk '{ sum += $2; n++ } END { if (n > 0) print sum / n; }' sys-time-4-16-80-15-1-5.txt

но я не знаю, как перебрать все файлы и создать файл результатов с тремя столбцами, как указано выше.

Ответы [ 2 ]

1 голос
/ 26 мая 2019

Вот сценарий оболочки, который использует GNU datamash для вычисления средних значений (хотя вы можете легко поменять их на awk, если хотите; я предпочитаю datamash для вычисления статистики):

#!/bin/sh

nums=$(mktemp)
sysmeans=$(mktemp)
knownmeans=$(mktemp)

for systime in sys-time-*.txt
do
    knownratio=$(echo -n "$systime" | sed -e 's/sys-time/known-ratio/')
    echo "$systime" | sed -E 's/.*-([0-9]+)-[0-9]+\.txt/\1/' >> "$nums"
    datamash -W mean 2 < "$systime" >> "$sysmeans"
    datamash -W mean 2 < "$knownratio" >> "$knownmeans"
done

paste "$nums" "$sysmeans" "$knownmeans"
rm -f "$nums" "$sysmeans" "$knownmeans"

Он создает три временных файла, по одному на столбец, и после заполнения их данными из каждой пары файлов, по одной паре на строку каждого, использует paste, чтобы объединить их все и вывести результат на стандартный вывод.

1 голос
/ 26 мая 2019

Я использовал GNU Awk для простых операций с файлами.Это не проверено;пожалуйста, дайте мне знать, как это работает.Возможно, вы захотите заглянуть в printf() для довольно распечатанного вывода.

mapfile -t Files < <(find . -type f -name "*-4-16-80-15-*" |sort -t\- -k7,7 -k8,8)  #1
gawk '
  BEGINFILE {n=split(FILENAME, f, "-"); type=f[1]; a[type]=0}                    #2
            {a[type] = ($2 + a[type] * c++) / c}                                 #3
  ENDFILE   {if(type=="sys") print f[n], a[sys], a[known]}                       #4
' "${Files[@]}"
  1. Создайте массив Bash с соответствующими файлами, отсортированными по двум последним «ключам».Мы передадим этот массив Awk позже.Обратите внимание, как мы чередуем файлы "sys" и "известные" в этом примере:
./known-ratio-4-16-80-15-2-150
./sys-time-4-16-80-15-2-150
./known-ratio-4-16-80-15-3-1
./sys-time-4-16-80-15-3-1
./known-ratio-4-16-80-15-3-50
./sys-time-4-16-80-15-3-50

В начале каждого файла очистите любое существующее среднее значение и сохраните тип как «sys» или «известный».

В каждой строке рассчитайте Совокупное скользящее среднее

В конце каждого файла проверяйте тип файла.Если мы только что обработали файл "sys", выведите последнюю часть имени файла и наши средние значения.

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