арифметическая операция над столбцом текстового файла - PullRequest
0 голосов
/ 03 мая 2019

У меня есть четыре столбца в моем текстовом файле. Мне нужно взять среднее значение четвертого столбца, соответствующего второму столбцу, и сохранить вывод в другом файле, который будет содержать только два столбца со средними результатами. Пожалуйста, помогите

ABC DEF IGK LMN
21  56700   001000  -98.3
24  56700   002000  -96.3
6   56700   003000  -93.8
9   56700   004000  -47.3
21  56700   005000  -58.3
36  56700   006000  -78.3
21  56701   001000  -98.3
28  56701   002000  -98.3
21  56701   003000  -99.3
20  56701   004000  -58.3
21  56701   005000  -99.3
10  56701   006000  -98.3
2   56701   007000  -87.3
2   56701   008000  -57.3
21  56702   001000  -63.3
1   56702   002000  -67.3
17  56702   003000  -47.3
21  56702   004000  -73.3
13  56702   005000  -60.3
10  56702   006000  -90.3
14  56702   007000  -77.3
11  56702   008000  -97.3
10  56702   009000  -98.3
13  56702   010000  -87.3
17  56702   011000  -77.3
11  56702   012000  -68.3

Ожидаемый результат:

DEF Average of LMN
56700   -78.71666667
56701   -87.05
56702   -75.63333333

Я могу получить общее среднее значение 4-го столбца за один раз, используя:

awk '{total+= $4} END {print total/NR}' inputfilename.txt

но мне нужно применить условие.

Ответы [ 3 ]

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

Используйте два массива, один для сумм; один для подсчета, сколько чисел добавлено к ним. В конце файла выведите DEF s и соответствующие средние значения.

awk 'NR>1{count[$2]++;total[$2]+=$4} END{for(key in count) print key, total[key]/count[key]}' file

Примечание: NR>1 предназначено для исключения строки заголовка, если фактический ввод не имеет строки заголовка, просто отбросьте его.

Учитывая ваш пример, его вывод выглядит так:

56700 -74.8
56701 -87.05
56702 -75.6333

Затем вы можете отсортировать вывод, используя sort, если это необходимо.

0 голосов
/ 03 мая 2019

, поскольку ваши исходные теги включают bash, вот пример с bash и bc -инструментом (не однострочным кодом, но иногда с надеждой изучить bash):

# only if needed in a short variable, later possible to test if exist, readable, ...
in=/path/to/your/testfile.txt
# we build a loop over your keys, possible
#  - for fixed length files and a fixed byte position
#    cut -b 5-10 
#  - for variable blocked with one (ore more) spaces as delimiter
#    sed -e 's/  */ /g' | cut -d ' ' -f 2   
for key in $(cat $in | cut -b 5-10 | sort -u) ; do
  # initialize counter for summary and number of elements per key
  s=0; a=0
  # grep all your relevant data from your inputfile (only for the key)
  # depends on your data you can grep on bytes (here from start of line with 4
  # characters and from byte 5-10 with your key)
  for x in $(grep -E "^.{4}${key}" $in | sed -e 's/  */ /g' | cut -d' ' -f4) ; do
    # count sum and add 1 to the number of entries
    s=$(echo "$s+$x" | bc --mathlib)
    ((a++))
  done
  # now print your key (as integer) and avg (as float with 6 decimals)
  printf "%i %.6f\n" $key $(echo "$s/$a" | bc --mathlib)
done

bc используется с параметром --mathlib с использованием шкалы 20. При необходимости или по вашему желанию вы можете использовать более высокую шкалу и уменьшать десятичные дроби только при печати результата.

Это решение с двумя циклами (одно для ключей, а другое для ключа) допустимо только в том случае, если количество белья в файле ввода не слишком велико (я не использую этот пример для миллиона строк), но оно более читабельно. как некоторый однострочный код (особенно для начинающих).

0 голосов
/ 03 мая 2019

Вы можете также рассмотреть возможность использования более мощного языка, особенно когда вам нужно сделать что-то более причудливое.

например. python

DEF_map = {}
with open('in.txt') as file:
    for line in file.readlines()[1:]:
        s = line.split()
        if s[1] not in DEF_map:
            DEF_map[s[1]] = []
        DEF_map[s[1]].append(float(s[3]))

print("DEF Average of LMN")
for DEF, LMN_list in DEF_map.items():
    print("{}\t{}".format(DEF, sum(LMN_list)/len(LMN_list)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...