Python код: форматирование "Мин" правильно, но "Макс" - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь обработать CSV-файл с данными о погоде.

Файл организован так, что первый столбец - это год, второй - месяц, третий - день месяца, четвертый - часы (от 00 до 23 в день), а пятый - часовая температура точки росы для каждого день года. Некоторые дни имеют значения температуры для каждого часа, а некоторые имеют несколько часов, которые -999 или отсутствуют.

Я пытаюсь извлечь минимальные и максимальные дневные значения из этих почасовых данных. Для этого у меня есть утверждение «если», отсортированное по месяцам, чтобы определить количество дней в месяце. Затем в операторе if я сортирую по дате, чтобы извлечь минимальную точку росы (minDP) и максимальную точку росы (maxDP) из часовых данных. Чтобы найти minDP и maxDP, у меня есть отдельные функции min и max с одинаковыми параметрами аргумента: для каждой даты с ежечасными данными возвращайте min или max, если точки росы больше -999, в противном случае возвращайте «M» для « отсутствует "если все почасовые данные за день -999. Секция minDP работает нормально, однако maxDP всегда возвращает пропущенные для всех дат, и я не понимаю, почему. В разделе maxDP, если я изменю функцию «max» на «min», она успешно возвращает min.

for m in months:
    if m == '01' or m =='03' or m == '05' or m == '07' or m == '08' or m == '10' or m == '12':
         dates = ['01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31']
         for d in dates:

             # For each date extract the minimum dewpoint, print "M" if all values for the date are less than -999
             with open('samplehourlydata.txt', 'r') as f:
                reader = csv.reader(f)
                next(reader)     # Skip header
                MinDP = min(row[4] if row[1] == m and row[2] == d and int(row[4]) > -999 else 'M' for row in reader)

            # For each date extract the maximum dewpoint, print "M" if all values for the date are less than -999
             with open('samplehourlydata.txt', 'r') as f:
                reader = csv.reader(f)
                next(reader)  # Skip header
                MaxDP = max(row[4] if row[1] == m and row[2] == d and int(row[4]) > -999 else 'M' for row in reader)
                print(year, m, d, MinDP, MaxDP)

Тот факт, что аргумент max выполняет часть «else» моего оператора if, заставляет меня думать, что он делает то, что я технически ему говорю. Тем не менее, я думаю, что я не должен говорить ему делать то, что я думаю. Однако тот факт, что простое изменение «max» на «min» в секции maxDP возвращает фактические значения min, кажется, подтверждает, что аргумент действителен ...

, если это помогает, данные CSV только для первого день выглядит так:

yyyy,mm,dd,hour,D.P.
2011,01,01,00, 27
2011,01,01,01, 28
2011,01,01,02, 27
2011,01,01,03, 26
2011,01,01,04, 26
2011,01,01,05, -999
2011,01,01,06, 28
2011,01,01,07, 27
2011,01,01,08, 28
2011,01,01,09, 29
2011,01,01,10, 31
2011,01,01,11, 34
2011,01,01,12, 37
2011,01,01,13, 39
2011,01,01,14, 40
2011,01,01,15, 42
2011,01,01,16, 44
2011,01,01,17, 43
2011,01,01,18, 43
2011,01,01,19, 43
2011,01,01,20, 43
2011,01,01,21, 42
2011,01,01,22, 44
2011,01,01,23, 44

и токовый выход с ошибочным maxDP выглядит так:

yyyy mm dd MinDP MaxDP
2011 01 01  26 M

Спасибо за любой ввод.

Ответы [ 2 ]

0 голосов
/ 22 апреля 2020

Вот возможное решение (которое не проверяет год, месяц, день), но использует YYY MM DD в качестве ключа к словарю. Значения хранятся в списке для этого года, месяца и дня.

Этот подход не открывает файл заново для каждого дня месяца, а суммирует их с указанием года, месяца, дня.

import csv

d = dict()

with open('f0.csv', 'r') as f:
    reader = csv.reader(f)
    next(reader) # drop header
    for row in reader:
        key = ' '.join(row[:3]) # YYYY MM DD
        d.setdefault(key, []).append(int(row[4]))

print ('yyyy mm dd MinDP MaxDP')

for key, vals in d.items():
    if all(v == -999 for v in vals):
        print(key, 'M', 'M')
    else:
        my_max = max(vals)
        my_min = min([v for v in vals if v != -999])
        print(key, my_min, my_max)

Для ваших данных я получил результат:

yyyy mm dd MinDP MaxDP
2011 01 01 26 44

ОБНОВЛЕНИЕ: код d.setdefault(key, []).append(int(row[4])) просто говорит, что ключ виден в первый раз, установите по умолчанию значение в списке, [], а затем добавить строку [4]. Если ключ уже был просмотрен, он просто добавляет строку [4].

Краткое введение в словари здесь и цикл по ним здесь

Кроме того, здесь есть ссылка на словари в geeksforgeeks , и вы можете найти дополнительную информацию Python там с помощью поиска.

Также обратите внимание, что при удалении ключа и его значений из словарь, будет выдано исключение, если ключ отсутствует в словаре. Итак, если вы не уверены, существует ли ключ в словаре, лучше сначала проверить с помощью:

if some_key in some_dict:
    del some_dict[some_key]

Вы можете извлечь значение из словаря, например var = dict_name[some_key], при условии, что ключ находится в словаре , Если это не так, вы получите исключение.

В этом случае, если вы не уверены, существует ли ключ, вы можете использовать get .

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

Поиск страниц по словарям.

0 голосов
/ 22 апреля 2020

try

MaxDP = max(row[4] if row[1] == m and row[2] == d and int(row[4]) > -999 else '\0' for row in reader)

'\ 0' - младший символ

...