Главная страница
Навигация по странице:

  • Таблица 16.1.

  • Рис. 16.2.

  • Рис. 16.3.

  • Рис. 16.4.

  • Рис. 16.5.

  • Рис. 16.6.

  • Книга Изучаем Python


    Скачать 4.68 Mb.
    НазваниеКнига Изучаем Python
    Дата10.12.2022
    Размер4.68 Mb.
    Формат файлаpdf
    Имя файлаErik_Metiz_Izuchaem_Python_Programmirovanie_igr_vizualizatsia_da.pdf
    ТипКнига
    #837531
    страница38 из 53
    1   ...   34   35   36   37   38   39   40   41   ...   53
    337
    по адресу https://www.nostarch.com/pythoncrashcourse/. Скопируйте файл sitka_weather_07-2014 .csv в каталог, в котором сохраняются программы этой главы.
    (После загрузки ресурсов книги в вашем распоряжении появятся все необходимые файлы для этого проекта.)
    ПРИМЕЧАНИЕ
    Погодные данные для этого проекта были загружены с сайта http://www .wunderground .com/history/ .
    Разбор заголовка файлов CSV
    Модуль Python csv из стандартной библиотеки разбирает строки файла CSV и по- зволяет быстро извлечь нужные значения. Начнем с первой строки файла, которая содержит серию заголовков данных:
    highs_lows.py
    import csv filename = 'sitka_weather_07-2014.csv'
     with open(filename) as f:
     reader = csv.reader(f)
     header_row = next(reader)
    print(header_row)
    После импортирования модуля csv имя обрабатываемого файла сохраняется в переменной filename
    . Затем файл открывается, а полученный объект сохраняется в переменной f
    . Далее программа вызывает метод csv.reader()
    и передает ему объект файла в аргументе, чтобы создать объект чтения данных для этого файла .
    Объект чтения данных сохраняется в переменной reader
    Модуль csv содержит функцию next()
    , которая возвращает следующую строку файла для полученного объекта чтения данных. В следующем листинге функция next()
    вызывается только один раз для получения первой строки файла, содержа- щей заголовки . Возвращенные данные сохраняются в header_row
    . Как видите, header_row содержит осмысленные имена заголовков, которые сообщают, какая информация содержится в каждой строке данных:
    ['AKDT', 'Max TemperatureF', 'Mean TemperatureF', 'Min TemperatureF',
    'Max Dew PointF', 'MeanDew PointF', 'Min DewpointF', 'Max Humidity',
    ' Mean Humidity', ' Min Humidity', ' Max Sea Level PressureIn',
    ' Mean Sea Level PressureIn', ' Min Sea Level PressureIn',
    ' Max VisibilityMiles', ' Mean VisibilityMiles', ' Min VisibilityMiles',
    ' Max Wind SpeedMPH', ' Mean Wind SpeedMPH', ' Max Gust SpeedMPH',
    'PrecipitationIn', ' CloudCover', ' Events', ' WindDirDegrees']
    Объект reader обрабатывает первую строку значений, разделенных запятыми, и со- храняет все значения в строке в списке. Заголовок
    AKDT
    означает «Alaska Daylight
    Time» (Аляска, летнее время). Позиция заголовка указывает на то, что первым значением в каждой из следующих строк является дата или время. Заголовок
    Max
    TemperatureF
    сообщает, что второе значение в каждой строке содержит максималь- ную температуру в этот день по шкале Фаренгейта. По именам заголовков можно определить, какая информация хранится в файле.

    338 Глава 16 • Загрузка данных
    ПРИМЕЧАНИЕ
    Форматирование заголовков не всегда последовательно; иногда встречаются лишние пробелы, единицы измерения находятся в неожиданных местах . В необработанных файлах данных это быва- ет достаточно часто, но не создает проблем .
    Печать заголовков и их позиций
    Чтобы читателю было проще понять структуру данных в файле, выведем каждый заголовок и его позицию в списке:
    highs_lows.py
    with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
     for index, column_header in enumerate(header_row):
    print(index, column_header)
    Мы применяем к списку функцию enumerate()
     для получения индекса каждого элемента и его значения. (Обратите внимание: строка print(header_row)
    удалена ради этой более подробной версии.)
    Результат с индексами всех заголовков выглядит так:
    0 AKDT
    1 Max TemperatureF
    2 Mean TemperatureF
    3 Min TemperatureF
    20 CloudCover
    21 Events
    22 WindDirDegrees
    Из этих данных видно, что даты и максимальные температуры за эти дни находятся в столбцах 0 и 1. Чтобы проанализировать температурные данные, мы обработа- ем каждую запись данных в файле sitka_weather_07-2014 .csv и извлечем элементы с индексами 0 и 1.
    Извлечение и чтение данных
    Итак, нужные столбцы данных известны; попробуем прочитать часть этих данных.
    Начнем с чтения максимальной температуры за каждый день:
    highs_lows.py
    import csv
    # Чтение максимальных температур из файла.
    filename = 'sitka_weather_07-2014.csv'
    with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)

    Формат CSV 339
     highs = []
     for row in reader:
     highs.append(row[1])
    print(highs)
    Программа создает пустой список с именем highs
     и перебирает остальные стро- ки в файле . Объект reader продолжает с того места, на котором он остановился в ходе чтения файла CSV, и автоматически возвращает каждую строку после текущей позиции. Так как заголовок уже прочитан, цикл продолжается со второй строки, в которой начинаются фактические данные. При каждом проходе цикла значение с индексом 1 (второй столбец) присоединяется к списку highs
    .
    В результате будет получен список highs со следующим содержимым:
    ['64', '71', '64', '59', '69', '62', '61', '55', '57', '61', '57', '59', '57',
    '61', '64', '61', '59', '63', '60', '57', '69', '63', '62', '59', '57', '57',
    '61', '59', '61', '61', '66']
    Мы извлекли максимальную температуру для каждого дня и аккуратно сохранили полученные данные в строковом формате в списке.
    Затем преобразуем строки в числа при помощи функции int()
    , чтобы данные можно было передать matplotlib
    :
    highs_lows.py
    highs = []
    for row in reader:
     high = int(row[1])
    highs.append(high)
    print(highs)
    Строки преобразуются в целые числа в точке  перед добавлением температур в список. Результат представляет собой список максимальных температур в чис- ловом формате:
    [64, 71, 64, 59, 69, 62, 61, 55, 57, 61, 57, 59, 57, 61, 64, 61, 59, 63, 60, 57,
    69, 63, 62, 59, 57, 57, 61, 59, 61, 61, 66]
    Следующим шагом станет построение визуализации этих данных.
    Нанесение данных на диаграмму
    Для наглядного представления температурных данных мы сначала создадим про- стую диаграмму дневных максимумов температуры с использованием matplotlib
    :
    highs_lows.py
    import csv from matplotlib import pyplot as plt

    340 Глава 16 • Загрузка данных
    # Чтение максимальных температур из файла.
    # Нанесение данных на диаграмму.
    fig = plt.figure(dpi=128, figsize=(10, 6))
     plt.plot(highs, c='red')
    # Форматирование диаграммы.
     plt.title("Daily high temperatures, July 2014", fontsize=24)
     plt.xlabel('', fontsize=16)
    plt.ylabel("Temperature (F)", fontsize=16)
    plt.tick_params(axis='both', which='major', labelsize=16)
    plt.show()
    Мы передаем при вызове plot()
    список highs
     и аргумент c='red'
    для отобра- жения точек красным цветом. (Максимумы будут выводиться красным цветом, а минимумы синим.) Затем указываются другие аспекты форматирования (напри- мер, размер шрифта и метки) , уже знакомые вам по главе 15. Так как даты еще не добавлены, метки для оси x не задаются, но вызов plt.xlabel()
    изменяет раз- мер шрифта, чтобы метки по умолчанию лучше читались . На рис. 16.1 показана полученная диаграмма: это простой график температурных максимумов за июль
    2014 г. в Ситке (штат Аляска).
    Рис. 16.1. График ежедневных температурных максимумов в июле 2014 г . в Ситке (штат Аляска)
    Модуль datetime
    Теперь нанесем даты на график, чтобы с ним было удобнее работать. Первая дата из файла погодных данных хранится во второй строке файла:
    2014-7-1,64,56,50,53,51,48,96,83,58,30,19,...

    Формат CSV 341
    Данные будут читаться в строковом формате, поэтому нам понадобится способ пре- образовать строку '2014-7-1'
    в объект, представляющий эту дату. Чтобы построить объект, соответствующий 1 июля 2014 года, мы воспользуемся методом strptime()
    из модуля datetime
    . Посмотрим, как работает strptime()
    в терминальном окне:
    >>> from datetime import datetime
    >>> first_date = datetime.strptime('2014-7-1', '%Y-%m-%d')
    >>> print(first_date)
    2014-07-01 00:00:00
    Сначала необходимо импортировать класс datetime из модуля datetime
    . Затем вызывается метод strptime()
    , первый аргумент которого содержит строку с датой.
    Второй аргумент сообщает Python, как отформатирована дата. В данном примере значение '%Y-'
    сообщает Python, что часть строки, предшествующая первому дефису, должна интерпретироваться как год из четырех цифр;
    '%m-'
    приказывает
    Python интерпретировать часть строки перед вторым дефисом как число, представ- ляющее месяц; наконец,
    '%d'
    приказывает Python интерпретировать последнюю часть строки как день месяца от 1 до 31.
    Метод strptime()
    может получать различные аргументы, которые описывают, как должна интерпретироваться запись даты. В табл. 16.1 перечислены некоторые из таких аргументов.
    Таблица 16.1. Аргументы форматирования даты и времени из модуля datetime
    Аргумент
    Описание
    %A
    Название дня недели — например, Monday
    %B
    Название месяца — например, January
    %m
    Порядковый номер месяца (от 01 до 12)
    %d
    День месяца (от 01 до 31)
    %Y
    Год из четырех цифр (например, 2015)
    %y
    Две последние цифры года (например, 15)
    %H
    Часы в 24-часовом формате (от 00 до 23)
    %I
    Часы в 12-часовом формате (от 01 до 12)
    %p
    AM или PM
    %M
    Минуты (от 00 до 59)
    %S
    Секунды (от 00 до 59)
    Представление дат на диаграмме
    Научившись обрабатывать данные в файлах CSV, вы сможете улучшить диаграмму температурных данных. Для этого мы извлечем из файла даты ежедневных макси- мумов и передадим даты и максимумы функции plot()
    :
    highs_lows.py
    import csv

    342 Глава 16 • Загрузка данных from datetime import datetime from matplotlib import pyplot as plt
    # Чтение дат и температурных максимумов из файла.
    filename = 'sitka_weather_07-2014.csv'
    with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
     dates, highs = [], []
    for row in reader:
     current_date = datetime.strptime(row[0], "%Y-%m-%d")
    dates.append(current_date)
    high = int(row[1])
    highs.append(high)
    # Нанесение данных на диаграмму.
    fig = plt.figure(dpi=128, figsize=(10, 6))
     plt.plot(dates, highs, c='red')
    # Форматирование диаграммы.
    plt.title("Daily high temperatures, July 2014", fontsize=24)
    plt.xlabel('', fontsize=16)
     fig.autofmt_xdate()
    plt.ylabel("Temperature (F)", fontsize=16)
    plt.tick_params(axis='both', which='major', labelsize=16)
    plt.show()
    Рис. 16.2. График с датами на оси x стал более понятным

    Формат CSV 343
    Мы создаем два пустых списка для хранения дат и температурных максимумов из файла . Затем программа преобразует данные, содержащие информацию даты
    (
    row[0]
    ), в объект datetime
    , который присоединяется к dates
    . Значения дат и температурных максимумов передаются plot()
    в точке . Вызов fig.autofmt_
    xdate()
    в точке  выводит метки дат по диагонали, чтобы они не перекрывались.
    На рис. 16.2 изображена новая версия графика.
    Расширение временного диапазона
    Итак, график успешно создан. Добавим на него новые данные для получения более полной картины погоды в Ситке. Скопируйте файл sitka_weather_2014 .csv
    , содержа- щий погодные данные для Ситки за целый год, в каталог с программами этой главы.
    А теперь мы можем сгенерировать график с погодными данными за год:
    highs_lows.py
    # Чтение дат и температурных максимумов из файла.
     filename = 'sitka_weather_2014.csv'
    with open(filename) as f:
    # Форматирование диаграммы.
     plt.title("Daily high temperatures - 2014", fontsize=24)
    plt.xlabel('', fontsize=16)
    Значение filename изменено, чтобы в программе использовался новый файл данных sitka_weather_2014 .csv
    , а заголовок диаграммы приведен в соответствие с содержимым .
    На рис. 16.3 изображена полученная диаграмма.
    Рис. 16.3. Данные за год

    344 Глава 16 • Загрузка данных
    Нанесение на диаграмму второй серии данных
    Обновленный график на рис. 16.3 содержит значительное количество полезных данных, но график можно сделать еще полезнее, добавив на него данные темпера- турных минимумов. Для этого необходимо прочитать температурные минимумы из файла данных и нанести их на график:
    highs_lows.py
    # Чтение дат, температурных максимумов и минимумов из файла.
    filename = 'sitka_weather_2014.csv'
    with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
     dates, highs, lows = [], [], []
    for row in reader:
    current_date = datetime.strptime(row[0], "%Y-%m-%d")
    dates.append(current_date)
    high = int(row[1])
    highs.append(high)
     low = int(row[3])
    lows.append(low)
    # Нанесение данных на диаграмму.
    fig = plt.figure(dpi=128, figsize=(10, 6))
    plt.plot(dates, highs, c='red')
     plt.plot(dates, lows, c='blue')
    # Формат диаграммы.
    x plt.title("Daily high and low temperatures - 2014", fontsize=24)
    Рис. 16.4. Две серии данных на одной диаграмме

    Формат CSV 345
    В точке  создается пустой список lows для хранения температурных минимумов, после чего программа извлекает и сохраняет температурный минимум для каждой даты из четвертой позиции каждой строки данных (
    row[3])
    . В точке  добавля- ется вызов plot()
    для температурных минимумов, которые окрашиваются в синий цвет. Затем остается лишь обновить заголовок диаграммы .
    На рис. 16.4 изображена полученная диаграмма.
    Цветовое выделение части диаграммы
    После добавления двух серий данных можно переходить к анализу диапазона температур по дням. Пора сделать последний штрих в оформлении диаграммы: затушевать диапазон между минимальной и максимальной дневной температу- рой. Для этого мы воспользуемся методом fill_between()
    , который получает серию значений x и две серии значений y и заполняет область между двумя значениями
    y
    :
    highs_lows.py
    # Нанесение данных на диаграмму.
    fig = plt.figure(dpi=128, figsize=(10, 6))
     plt.plot(dates, highs, c='red', alpha=0.5)
    plt.plot(dates, lows, c='blue', alpha=0.5)
     plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
    Аргумент alpha
     определяет степень прозрачности вывода. Значение 0 означает полную прозрачность, а 1 (по умолчанию) — полную непрозрачность. Со значением alpha=0.5
    красные и синие линии на графике становятся более светлыми.
    Рис. 16.5. Область между двумя наборами данных закрашена

    346 Глава 16 • Загрузка данных
    В точке  fill_between()
    передается список dates для значений x и две серии значений y highs и lows
    . Аргумент facecolor определяет цвет закрашиваемой об- ласти; мы назначаем ему низкое значение alpha=0.1
    , чтобы заполненная область соединяла две серии данных, не отвлекая зрителя от передаваемой информации.
    На рис. 16.5 показана диаграмма с закрашенной областью между highs и lows
    Закрашенная область подчеркивает величину расхождения между двумя наборами данных.
    Проверка ошибок
    Программа highs_lows .py должна нормально работать для погодных данных любого места. Однако на некоторых метеорологических станциях происходят сбои, и стан- циям не удается собрать данные (полностью или частично). Отсутствие данных может привести к исключениям; если исключения не будут обработаны, то про- грамма аварийно завершится.
    Для примера попробуем построить график температур для Долины Смерти (штат
    Калифорния). Скопируйте файл death_valley_2014 .csv в каталог с программами этой главы, после чего внесите изменения в highs_lows .py для работы с другим набором данных:
    highs_lows.py
    # Чтение дат, температурных максимумов и минимумов из файла.
    filename = 'death_valley_2014.csv'
    with open(filename) as f:
    При запуске программы происходит ошибка, как видно из последней строки сле- дующего вывода:
    Traceback (most recent call last):
    File "highs_lows.py", line 17, in high = int(row[1])
    ValueError: invalid literal for int() with base 10: ''
    Трассировка показывает, что Python не может обработать максимальную температу- ру для одной из дат, потому что не может преобразовать пустую строку
    ('')
    в целое число. Чтобы понять причину, достаточно заглянуть в файл death_valley_2014 .csv
    :
    2014-2-16,,,,,,,,,,,,,,,,,,,0.00,,,-1
    Похоже, 16 февраля 2014 года данные не сохранялись; строка максимальной тем- пературы пуста. Чтобы решить проблему, мы будем выполнять проверку ошибок при чтении данных из файла для обработки исключений, которые могут возникнуть при разборе наборов данных. Вот как это делается:
    highs_lows.py
    # Чтение дат, температурных максимумов и минимумов из файла.
    filename = 'death_valley_2014.csv'

    Формат CSV 347
    with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
    dates, highs, lows = [], [], []
    for row in reader:
     try:
    current_date = datetime.strptime(row[0], "%Y-%m-%d")
    high = int(row[1])
    low = int(row[3])
    except ValueError:
     print(current_date, 'missing data')
    else:
     dates.append(current_date)
    highs.append(high)
    lows.append(low)
    # Plot data.
    # Форматирование диаграммы
     title = "Daily high and low temperatures - 2014\nDeath Valley, CA"
    plt.title(title, fontsize=20)
    При анализе каждой строки данных мы пытаемся извлечь дату, максимальную и минимальную температуру . Если каких-либо данных не хватает, Python вы- дает ошибку
    ValueError
    , а мы обрабатываем ее — выводим сообщение с датой, для которой отсутствуют данные . После вывода ошибки цикл продолжает обработку следующей порции данных. Если все данные, относящиеся к некоторой дате, про- читаны без ошибок, выполняется блок else
    , а данные присоединяются к соответ- ствующим спискам . Так как на диаграмме отображается информация для нового места, заголовок изменяется, и в него включается название места .
    Рис. 16.6. Максимальная и минимальная температура в Долине Смерти

    348 Глава 16 • Загрузка данных
    При выполнении highs_lows .py мы видим, что данные отсутствуют только для одной даты:
    2014-02-16 missing data
    Полученная диаграмма изображена на рис. 16.6.
    Сравнивая эту диаграмму с диаграммой для Ситки, мы видим, что в Долине Смер- ти теплей, чем на юго-востоке Аляски (как и следовало ожидать), но при этом температурный диапазон в пустыне более широкий. Высота закрашенной области наглядно демонстрирует этот факт.
    Во многих наборах данных, с которыми вы будете работать, будут встречаться от- сутствующие, неправильно отформатированные или некорректные данные. В таких ситуациях воспользуйтесь теми инструментами, которые вы освоили в первой половине книги. В данном примере для обработки отсутствующих данных исполь- зовался блок try
    - except
    - else
    . Иногда команда continue используется для пропуска части данных, или же данные удаляются после извлечения вызовом remove()
    или del
    . Используйте любое работающее решение — лишь бы в результате у вас полу- чилась осмысленная, точная визуализация.
    1   ...   34   35   36   37   38   39   40   41   ...   53


    написать администратору сайта