Как рассчитать среднее значение месяца столбца месяца с годами?

1 метод будет

sudo find / -type f | wc -l
sudo find / -type d | wc -l

(sudo для предотвращения доступа к ошибкам) ​​

f для файлов, d для каталогов.

The / proc / файловая система будет выходить из строя, но я не рассматриваю эти файлы;)

1
задан 3 June 2017 в 14:21

8 ответов

Вы можете сделать это с помощью небольшого скрипта Python:

#!/usr/bin/env python3 import sys if len(sys.argv) != 2: print("You must provide exactly one filename to read as argument.") exit(-1) file = open(sys.argv[1]) file.readline() # to strip headline dict = {} for line in file: datestr, tempstr = line.split()[4:] year, temp = int(datestr.split("/")[-1]), float(tempstr) dict.setdefault(year, []).append(temp) for year in dict: print("{0}:\t{1:.2f}".format(year, sum(dict[year]) / len(dict[year])))

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

Ниже приведен пример с файлом данных vk4.txt, который вы указали. Я сохранил сценарий выше как avgtemp.py в текущем каталоге и сделал его исполняемым с помощью chmod +x avgtemp.py:

$ ./avgtemp.py vk4.txt 2012: 32.22 2013: 34.30

. Если вы хотите, точный формат вывода можно легко изменить, просто отредактировав "{0}:\t{1:.2f}" в последней строке скрипта. Здесь вы можете ввести любой шаблон, если он содержит {0}, чтобы заменить его на год и {1:.2f} или аналогичный, чтобы заменить его на среднюю температуру, отображаемую двумя десятичными цифрами. [F9] - вкладка.

0
ответ дан 18 July 2018 в 12:13

Это может быть больше подходит для переполнения стека; однако, вот решение, использующее Python, в котором вы должны заменить temperature_data.txt в первой строке вашим файлом.

f=open("temperature_data.txt","r") ### REPLACE temperature_data.txt WITH THE FILE CONTAINING YOUR DATA flines=f.readlines() #read the file in question f.close() flines_split=[line.split() for line in flines] #split each line up data_split=[line for line in flines_split if len(line)>=5 and line[4].count("/")==2] #get only lines with the date in gathered_data={} for line in data_split: #this block sanitises the data month=int(line[4][:2]) ### NOTE THAT THIS ASSUMES YOU ARE USING AMERICAN DATE FORMAT ### IF YOU ARE NOT, REPLACE "month=int(line[4][:2])" WITH "month=int(line[4][3:5])" year=int(line[4][6:]) if (month,year) in gathered_data: gathered_data[(month,year)].append(float(line[5])) else: gathered_data[(month,year)]=[float(line[5])] def mean(l): #function to calculate means return sum(l)/float(len(l)) means={k:mean(gathered_data[k]) for k in gathered_data} #calculate means print("Month Year Temperature") for k in sorted(list(means)): #print output print("{date[0]:^5} {date[1]} {temp:.4}".format(date=k,temp=means[k])) ### the 4 in {temp:.4} specifies precision and can be modified.
0
ответ дан 18 July 2018 в 12:13

Решение Perl

Вот однострочная команда, которая работает с предпосылкой построения двух хэшей - $h1 для суммирования значений температуры и $h2 для хранения общего количества обработанных записей. Каждая соответствующая строка будет содержать тот же ключ в формате MMYYYY, который извлекается из вашего столбца №5 (который для индекса perl массива # 4, то есть $F[4]):

perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }'

Ключевые точки здесь:

используем do {} if condition1 and condition2 структура. Действие {} выполняется только тогда, когда номер строки не равен 1 (т. Е. Мы пропускаем заголовок), и существует $F[4] (т. Е. Мы избегаем пустых или неполных строк). @a=split "/",$F[4] позволяет нам разбивать штамп даты MM/DD/YYYY на части, а с помощью $k= $a[0] . $a[2] мы создаем ключевую переменную, которая позволит нам хранить данные в двух хэшах. Структура END{} будет выполнять действие, когда весь файл будет считан.

Решение работает достаточно хорошо. Вот тест с 1100 000 строк ввода:

bash-4.3$ time perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }' big_input.txt 052012 32.4666666666021 042012 31.8250000001141 042013 34.3000000000646 real 0m8.600s user 0m8.480s sys 0m0.032s bash-4.3$ wc -l big_input.txt 1100000 big_input.txt

ПРИМЕЧАНИЕ: для формата csv используйте perl -a -F',' -lne вместо

0
ответ дан 18 July 2018 в 12:13

Основная идея будет заключаться в создании ключа года из поля даты, а затем суммирования и подсчета записей на основе этого ключа с использованием ассоциативных массивов, например

awk ' NR>1 { split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++; } END { for (i in s) print i, s[i]/c[i] }' vk4.txt

Тестирование с вашими данными:

$ mawk ' NR>1 { split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++; } END { for (i in s) print i, s[i]/c[i]; }' vk4.txt 2012/04 31.9667 2012/05 32.4667 2013/04 34.3

Если у вас есть GNU awk (gawk) v4 +, вы можете добавить явную сортировку.

0
ответ дан 18 July 2018 в 12:13

Вы можете сделать это с помощью небольшого скрипта Python:

#!/usr/bin/env python3 import sys if len(sys.argv) != 2: print("You must provide exactly one filename to read as argument.") exit(-1) file = open(sys.argv[1]) file.readline() # to strip headline dict = {} for line in file: datestr, tempstr = line.split()[4:] year, temp = int(datestr.split("/")[-1]), float(tempstr) dict.setdefault(year, []).append(temp) for year in dict: print("{0}:\t{1:.2f}".format(year, sum(dict[year]) / len(dict[year])))

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

Ниже приведен пример с файлом данных vk4.txt, который вы указали. Я сохранил сценарий выше как avgtemp.py в текущем каталоге и сделал его исполняемым с помощью chmod +x avgtemp.py:

$ ./avgtemp.py vk4.txt 2012: 32.22 2013: 34.30

. Если вы хотите, точный формат вывода можно легко изменить, просто отредактировав "{0}:\t{1:.2f}" в последней строке скрипта. Здесь вы можете ввести любой шаблон, если он содержит {0}, чтобы заменить его на год и {1:.2f} или аналогичный, чтобы заменить его на среднюю температуру, отображаемую двумя десятичными цифрами. [F9] - вкладка.

0
ответ дан 24 July 2018 в 19:55
  • 1
    Traceback (последний последний вызов): Файл & quot; ./ av_temp.py & quot ;, строка 13, в & lt; module & gt; datestr, tempstr = line.split () [4:] ValueError: недостаточно значений для распаковки (ожидается 2, получено 0), когда я запускаю этот скрипт, тогда он показывает приведенный выше код ошибки. – Vaibhav Kumar 5 June 2017 в 09:52
  • 2
    @VaibhavKumar Это означает, что вы читаете файл, который не имеет ровно 6 столбцов в каждой строке, кроме первой, которая игнорируется. Проверьте формат входного файла. – Byte Commander 5 June 2017 в 14:56
  • 3
    Работает красиво. С 1 миллионом строк входного файла потребовалось 0m09.07s real в моей системе для выполнения вычислений – Sergiy Kolodyazhnyy 28 June 2017 в 00:13

Это может быть больше подходит для переполнения стека; однако, вот решение, использующее Python, в котором вы должны заменить temperature_data.txt в первой строке вашим файлом.

f=open("temperature_data.txt","r") ### REPLACE temperature_data.txt WITH THE FILE CONTAINING YOUR DATA flines=f.readlines() #read the file in question f.close() flines_split=[line.split() for line in flines] #split each line up data_split=[line for line in flines_split if len(line)>=5 and line[4].count("/")==2] #get only lines with the date in gathered_data={} for line in data_split: #this block sanitises the data month=int(line[4][:2]) ### NOTE THAT THIS ASSUMES YOU ARE USING AMERICAN DATE FORMAT ### IF YOU ARE NOT, REPLACE "month=int(line[4][:2])" WITH "month=int(line[4][3:5])" year=int(line[4][6:]) if (month,year) in gathered_data: gathered_data[(month,year)].append(float(line[5])) else: gathered_data[(month,year)]=[float(line[5])] def mean(l): #function to calculate means return sum(l)/float(len(l)) means={k:mean(gathered_data[k]) for k in gathered_data} #calculate means print("Month Year Temperature") for k in sorted(list(means)): #print output print("{date[0]:^5} {date[1]} {temp:.4}".format(date=k,temp=means[k])) ### the 4 in {temp:.4} specifies precision and can be modified.
0
ответ дан 24 July 2018 в 19:55
  • 1
    Когда я использовал скрипт для получения вывода, тогда он показывает python3 script.py Month Year Temperature – Vaibhav Kumar 7 June 2017 в 10:28

Решение Perl

Вот однострочная команда, которая работает с предпосылкой построения двух хэшей - $h1 для суммирования значений температуры и $h2 для хранения общего количества обработанных записей. Каждая соответствующая строка будет содержать тот же ключ в формате MMYYYY, который извлекается из вашего столбца №5 (который для индекса perl массива # 4, то есть $F[4]):

perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }'

Ключевые точки здесь:

используем do {} if condition1 and condition2 структура. Действие {} выполняется только тогда, когда номер строки не равен 1 (т. Е. Мы пропускаем заголовок), и существует $F[4] (т. Е. Мы избегаем пустых или неполных строк). @a=split "/",$F[4] позволяет нам разбивать штамп даты MM/DD/YYYY на части, а с помощью $k= $a[0] . $a[2] мы создаем ключевую переменную, которая позволит нам хранить данные в двух хэшах. Структура END{} будет выполнять действие, когда весь файл будет считан.

Решение работает достаточно хорошо. Вот тест с 1100 000 строк ввода:

bash-4.3$ time perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }' big_input.txt 052012 32.4666666666021 042012 31.8250000001141 042013 34.3000000000646 real 0m8.600s user 0m8.480s sys 0m0.032s bash-4.3$ wc -l big_input.txt 1100000 big_input.txt

ПРИМЕЧАНИЕ: для формата csv используйте perl -a -F',' -lne вместо

0
ответ дан 24 July 2018 в 19:55

Основная идея будет заключаться в создании ключа года из поля даты, а затем суммирования и подсчета записей на основе этого ключа с использованием ассоциативных массивов, например

awk ' NR>1 { split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++; } END { for (i in s) print i, s[i]/c[i] }' vk4.txt

Тестирование с вашими данными:

$ mawk ' NR>1 { split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++; } END { for (i in s) print i, s[i]/c[i]; }' vk4.txt 2012/04 31.9667 2012/05 32.4667 2013/04 34.3

Если у вас есть GNU awk (gawk) v4 +, вы можете добавить явную сортировку.

1
ответ дан 24 July 2018 в 19:55
  • 1
    IMDE1611_14164B (PITAMPURA), 28,7,77.15,1,04 / 05 / 2012,31,4 IMDE1611_14164B (PITAMPURA), 28,7,77,15,0,04 / 05 / 2012,31,9 IMDE1611_14164B (PITAMPURA), 28,7,77,15,0,04 / 03 /2013,34.1 IMDE1611_14164B (PITAMPURA), 28.7,77.15,8,04 / 03 / 2013,34.6 мой файл находится в формате csv, и когда я использовал приведенный выше сценарий для вычисления среднего значения темпа (шестой столбец) каждый год, показать 0 выход. – Vaibhav Kumar 7 June 2017 в 08:00
  • 2
    @VaibhavKumar это отличается от того, что сказано в вашем оригинальном посте. Пожалуйста, будьте последовательны. Если файл находится в формате csv, скажите так в вопросе. Мы не должны извлекать эту информацию из комментариев – Sergiy Kolodyazhnyy 28 June 2017 в 00:14

Другие вопросы по тегам:

Похожие вопросы: