awk: математические операции с данными из нескольких столбцов в нескольких файлах CSV.

Я работаю над сценарием bash, который зацикливает заполнение данных с несколькими столбцами и выполняет интегрированный код AWK для работы с данными с несколькими столбцами.

#!/bin/bash
home="$PWD"
# folder with the outputs
rescore="${home}"/rescore 
# folder with the folders to analyse
storage="${home}"/results
    

while read -r d; do
awk -F ", *" '                  # set field separator to comma, followed by 0 or more whitespaces
FNR==1 {
   if (n) {                     # calculate the results of previous file
     f=                   # apply this equation to rescore data using values of $3 and $2
      f[suffix] = f          # store the results in the array
      n=$1 # take ID of the column
   }
   prefix=suffix=FILENAME
   sub(/_.*/, "", prefix)
   sub(/\/[^\/]+$/, "", suffix)
   sub(/^.*_/, "", suffix)
   n = 1                        # count of samples
   min = 0                      # lowest value of $3 (assuming all $3 < 0)
}
FNR > 1 {
   s += $3
   s2 += $3 * $3
   ++n
   if ($3 < min) min = $3       # update the lowest value
}
   print "ID" prefix, rescoring
   for (i in n)
      printf "%s %.2f\n", i, f[i]
}'  "${d}_"*/input.csv > "${rescore}/"${d%%_*}".csv"
done < <(find . -maxdepth 1 -type d -name '*_*_*' | awk -F '[_/]' '!seen[$2]++ {print $2}')

Вкратце, рабочий процесс должен обрабатывать каждую строку input.csv, расположенную внутри папки ${d}, которая правильно определена моим скриптом bash:

# input.csv located in the folder 10V1_cne_lig12
ID, POP, dG
1, 142, -5.6500 # this is dG(min)
2, 10, -5.5000
3, 2, -4.9500
4, 150, -4.1200

Ожидается, что мой сценарий AWK будет обрабатывать каждую строку каждого файла CSV, чтобы сократить их до двух столбцов, сохраняя на выходе: i) число из первого столбца input.csv (содержащее идентификатор обработанной строки) + имя папки ($d) содержало CSV-файл, а также ii) результат математической операции (f), примененной к числам в столбцах POP и dG файла input.csv:

f(ID)= sqrt(((dG(ID)+10)/10)^2+((POP(ID)-240)/240))^2)

где dG(ID) — это значение dG (3 доллара США) переоцененной строки input.csv, а POP(ID) — это значение POP ($2). следующий формат:

# output.csv
ID,             rescore value
1 10V1_cne_lig12,  f(ID1)
2 10V1_cne_lig12,  f(ID2)
3 10V1_cne_lig12,  f(ID3)
4 10V1_cne_lig12,  f(ID4)

В то время как часть моего кода bash (имеющая дело с зацикливанием CSV в разных каталогах) работает правильно, я застрял в коде AWK, который неправильно назначает идентификаторы строк, чтобы я мог применять продемонстрированные математические операции, используя $2 и $3 столбцы строки с уточненным ID.


person Community    schedule 11.05.2021    source источник
comment
Откуда взялся 10V1_cne_lig12?   -  person karakfa    schedule 11.05.2021
comment
все папки (содержащие input.csv) расположены внутри $storage, который был определен в части bash (и работает правильно!) Буквально мы зацикливаем в bash множество папок в $storage (каждая из которых содержит три столбца input. csv), а затем примените код AWK для каждого файла csv.   -  person    schedule 11.05.2021
comment
мы не знаем ваших данных. Мы видим только то, что вы публикуете здесь. Где вы планируете извлечь эту строку? Это имя файла, одно из существующих полей, должно быть получено из других полей, константа?   -  person karakfa    schedule 11.05.2021
comment
На самом деле это имя папки (содержащей csv), которое должно быть непосредственно извлечено и упомянуто рядом с идентификатором первого столбца... но для простоты вы можете просто написать пример части AWK, сосредоточив внимание только на математическом уравнении, как это может быть применяется только к одному CSV-файлу для обработки второго и третьего столбцов... заранее большое спасибо!   -  person    schedule 11.05.2021


Ответы (1)


учитывая входной файл: папка/файл

ID, POP, dG
1, 142, -5.6500 
2, 10, -5.5000
3, 2, -4.9500
4, 150, -4.1200

этот сценарий

$ awk -F', *' -v OFS=', ' '
        FNR==1 {path=FILENAME; sub(/\/[^/]+$/,"",path); print $1,"rescore value"; next} 
               {print $1" "path, sqrt((($3+10)/10)^2+(($2-240)/240)^2)}' folder/file

будет производить

ID, rescore value
1 folder, 0.596625
2 folder, 1.05873
3 folder, 1.11285
4 folder, 0.697402

Не уверен, что делает остальная часть вашего кода, но я думаю, вы можете интегрировать его.

person karakfa    schedule 11.05.2021
comment
Да спасибо! теперь часть AWK работает очень хорошо! Один вопрос - возможно ли передать (чтобы я мог использовать его при необходимости для сравнения моих данных) ваше решение AWK с чем-то вроде sed, которое будет дополнительно фильтровать вывод и сокращать его до одной строки: сохраняя только первый столбец из заголовка (1-я строка) + значение dG из строки, содержащей наименьшее значение + его идентификатор в (). Для нашего примера отфильтрованный вывод должен быть: ID, 0.596625 (1) . - person ; 12.05.2021
comment
только что создал новую тему, демонстрирующую мой код bash/awk для ясности: stackoverflow.com/questions/67501145/ - person ; 12.05.2021