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

  • Рис. 16.6.

  • УПРАЖНЕНИЯ 16.1. Осадки в Ситке

  • 16.2. Сравнение Ситки с Долиной Смерти

  • 16.4. Автоматические индексы

  • Мэтиз. Изучаем Python. Crash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g


    Скачать 6.2 Mb.
    НазваниеCrash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g
    Дата28.06.2022
    Размер6.2 Mb.
    Формат файлаpdf
    Имя файлаМэтиз. Изучаем Python.pdf
    ТипДокументы
    #618322
    страница39 из 52
    1   ...   35   36   37   38   39   40   41   42   ...   52
    358 Глава 16 • Загрузка данных
    death_valley_highs_lows.py
    filename = 'data/death_valley_2018_simple.csv'
    with open(filename) as f:
    # Получение дат, температурных минимумов и максимумов из файла.
    dates, highs, lows = [], [], []
    for row in reader:
    current_date = datetime.strptime(row[2], '%Y-%m-%d')

    high = int(row[4])
    low = int(row[5])
    dates.append(current_date)
    В точке  индексы обновляются в соответствии с позициями
    TMAX
    и
    TMIN
    в данном файле.
    При запуске программы происходит ошибка, как видно из последней строки сле- дующего вывода:
    Traceback (most recent call last):
    File "death_valley_highs_lows.py", line 15, in high = int(row[4])
    ValueError: invalid literal for int() with base 10: ''
    Трассировка показывает, что Python не может обработать максимальную темпе- ратуру для одной из дат, потому что не может преобразовать пустую строку
    ('')
    в целое число. Вместо того чтобы копаться в данных и искать отсутствующее зна- чение, мы обработаем ситуации с отсутствием данных напрямую.
    При чтении данных из CSV-файла будет выполняться код проверки ошибок для обработки исключений, которые могут возникнуть при разборе наборов данных.
    Вот как это делается:
    death_valley_highs_lows.py
    # Чтение дат, температурных максимумов и минимумов из файла.
    filename = 'death_valley_2018_simple.csv'
    with open(filename) as f:
    for row in reader:
    current_date = datetime.strptime(row[2], '%Y-%m-%d')

    try:
    high = int(row[4])
    low = int(row[5])
    except ValueError:

    print(f"Missing data for {current_date}")

    else:
    dates.append(current_date)
    highs.append(high)
    lows.append(low)

    Формат CSV 359
    # Нанесение данных на диаграмму.
    # Форматирование диаграммы

    title = "Daily high and low temperatures - 2018\nDeath Valley, CA"
    plt.title(title, fontsize=20)
    plt.xlabel('', fontsize=16)
    При анализе каждой строки данных мы пытаемся извлечь дату, максимальную и минимальную температуру . Если каких-либо данных не хватает, Python вы- дает ошибку
    ValueError
    , а мы обрабатываем ее — выводим сообщение с датой, для которой отсутствуют данные . После вывода ошибки цикл продолжает об- работку следующей порции данных. Если все данные, относящиеся к некоторой дате, прочитаны без ошибок, выполняется блок else
    , а данные присоединяются к соответствующим спискам . Так как на диаграмме отображается информация для нового места, заголовок изменяется, в него включается название места, а для вывода длинного заголовка используется уменьшенный шрифт .
    При выполнении death_valley_highs_lows .py мы видим, что данные отсутствуют только для одной даты:
    Missing data for 2018-02-18 00:00:00
    Так как ошибка была обработана корректно, наш код может сгенерировать диа- грамму, в которой пропущены отсутствующие данные. Полученная диаграмма изображена на рис. 16.6.
    Рис. 16.6. Максимальная и минимальная температура в Долине Смерти

    360 Глава 16 • Загрузка данных
    Сравнивая эту диаграмму с диаграммой для Ситки, мы видим, что в Долине Смерти теплее, чем на юго-востоке Аляски (как и следовало ожидать), но при этом темпера- турный диапазон в пустыне более широкий. Высота закрашенной области наглядно демонстрирует этот факт.
    Во многих наборах данных, с которыми вы будете работать, вам встретятся отсут- ствующие, неправильно отформатированные или некорректные данные. В таких ситуациях воспользуйтесь теми инструментами, которые вы освоили в первой половине книги. В данном примере для обработки отсутствующих данных исполь- зовался блок try
    - except
    - else
    . Иногда команда continue используется для пропуска части данных или же данные удаляются после извлечения вызовом remove()
    или del
    . Используйте любое работающее решение — лишь бы в результате у вас полу- чилась осмысленная, точная визуализация.
    Загрузка собственных данных
    Если вы предпочитаете загрузить собственные погодные данные, выполните сле- дующие действия:
    1. Посетите сайт NOAA Climate Data Online по адресу https://www .ncdc .noaa .gov/
    cdo-web/
    . В разделе
    Discover
    Data щелкните на кнопке
    Search
    Tool
    . В поле
    Select a
    Dataset выберите вариант
    Daily
    Summaries
    2. Выберите диапазон дат. В разделе
    Search
    For выберите вариант
    ZIP
    Codes
    . Введите zip-код интересующего вас места и щелкните на кнопке
    Search
    3. На следующей странице отображается карта и информация об области, на кото- рой вы хотите сосредоточиться. Под названием места щелкните на кнопке
    View
    Full
    Details либо щелкните на карте, а затем выберите вариант
    Full
    Details
    4. Прокрутите данные и щелкните на кнопке
    Station
    List
    , чтобы просмотреть список метеорологических станций в этой области. Выберите одну из станций и щелк- ните на кнопке
    Add to
    Cart
    . Данные распространяются бесплатно, несмотря на то что на сайте используется обозначение покупательской корзины. Щелкните на изображении корзины в правом верхнем углу.
    5. Выберите
    Output
    , затем
    Custom
    GHCN-Daily
    CSV
    . Проверьте на правильность диа- пазон дат и щелкните на кнопке
    Continue
    6. На следующей странице вы можете выбрать нужные разновидности данных.
    Например, можно загрузить один тип данных, ограничившись температурой воздуха, или же загрузить все данные, собираемые станцией. Выберите нужный вариант и щелкните на кнопке
    Continue
    7. На последней странице выводится сводка запроса. Введите свой адрес электрон- ной почты и щелкните на кнопке
    Submit
    Order
    . Вы получите подтверждение запроса, а через несколько минут придет другое сообщение электронной почты со ссылкой для загрузки данных.

    Построение карт с глобальными наборами данных: формат JSON 361
    Загруженные данные будут иметь такую же структуру, как и те данные, с которыми вы работали в этом разделе. Их заголовки могут отличаться от представленных в этом разделе, но если вы последуете описанной процедуре, вы сможете построить визуализации интересующих вас данных.
    УПРАЖНЕНИЯ
    16.1. Осадки в Ситке: Ситка находится в зоне умеренных лесов, поэтому в этой местности выпадает достаточно осадков. В файле данных sitka_weather_2018_simple .csv присутствует заголовок PRCP, представляющий величину ежедневных осадков. Постройте диаграмму по данным этого столбца. Повторите упражнение для Долины Смерти, если вас интересует, сколько осадков выпадает в пустыне.
    16.2. Сравнение Ситки с Долиной Смерти: разные масштабы температур отражают разные диапазоны данных. Чтобы точно сравнить температурный диапазон в Ситке с температур- ным диапазоном Долины Смерти, необходимо установить одинаковый масштаб по оси y
    Измените параметры оси y
    для одной или обеих диаграмм на рис. 16.5 и 16.6 и проведите прямое сравнение температурных диапазонов в этих двух местах (или любых других, кото- рые вас интересуют).
    16.3. Сан-Франциско: к какому месту ближе температура в Сан-Франциско: к Ситке или
    Долине Смерти? Загрузите данные для Сан-Франциско, постройте температурную диа- грамму для Сан-Франциско и сравните.
    16.4. Автоматические индексы: в этом разделе индексы, соответствующие столбцам TMIN и TMAX, были жестко зафиксированы в коде. Используйте строку данных заголовка для определения индексов этих значений, чтобы ваша программа работала как для Ситки, так и для Долины Смерти. Используйте название станции, чтобы автоматически сгенериро- вать подходящий заголовок для вашей диаграммы.
    16.5. Исследования: постройте еще несколько визуализаций, отражающих любые другие аспекты погоды для интересующих вас мест.
    Построение карт с глобальными наборами данных: формат JSON
    В этом разделе мы загрузим данные о землетрясениях, произошедших в мире за последний месяц. Затем построим карту, на которой будут обозначены эти зем- летрясения с указанием их силы. Так как данные хранятся в формате JSON, для работы с ними будет использован модуль json
    . С помощью удобных средств Plotly для работы с картами, мы построим визуализации, отражающие глобальное рас- пределение землетрясений.
    Загрузка данных землетрясений
    Скопируйте файл eq_1_day_m1 .json в каталог, в котором хранятся данные программ этой главы. Землетрясения классифицируются по магнитуде по шкале Рихтера.
    Файл включает данные по всем землетрясениям с магнитудой M1 и выше, про-

    362 Глава 16 • Загрузка данных изошедшим за последние 24 часа (на момент написания книги). Данные взяты из одного потока данных Геологического управления США, доступных по адресу https://earthquake .usgs .gov/earthquakes/feed/
    Знакомство с данными
    Открыв файл eq_1_day_m1 .json
    , вы увидите, что данные упакованы очень плотно и плохо читаются:
    {"type":"FeatureCollection","metadata":{"generated":1550361461000,...
    {"type":"Feature","properties":{"mag":1.2,"place":"11km NNE of Nor...
    {"type":"Feature","properties":{"mag":4.3,"place":"69km NNW of Ayn...
    {"type":"Feature","properties":{"mag":3.6,"place":"126km SSE of Co...
    {"type":"Feature","properties":{"mag":2.1,"place":"21km NNW of Teh...
    {"type":"Feature","properties":{"mag":4,"place":"57km SSW of Kakto...
    Формат этого файла больше предназначен для машин, нежели для людей. Но мы видим, что файл содержит словари, а также информацию, которая нас интересует, включая магнитуды и местоположения землетрясений.
    Модуль json предоставляет разнообразные инструменты для анализа и обработки данных JSON. Некоторые из этих инструментов позволяют переформатировать файл, чтобы вам было удобнее работать с необработанными данными, прежде чем вы начнете работать с ними на программном уровне.
    Для начала загрузим данные и выведем их в формате, лучше подходящем для чтения. Файл очень длинный, поэтому вместо того, чтобы выводить его, запишем данные в новый файл. После этого вы сможете открыть этот файл и прокрутить его к нужной позиции:
    eq_explore_data.py
    import json
    # Изучение структуры данных.
    filename = 'data/eq_data_1_day_m1.json'
    with open(filename) as f:

    all_eq_data = json.load(f)

    readable_file = 'data/readable_eq_data.json'
    with open(readable_file, 'w') as f:

    json.dump(all_eq_data, f, indent=4)
    Начнем с импортирования модуля json
    , чтобы загрузить данные из файла, а затем сохранить весь набор данных в all_eq_data
    . Функция json.load()
    преобразует данные в формат, с которым может работать Python: в данном случае огромный словарь. В точке  создается файл для записи тех же данных в более удобочитае- мый формат. Функция json.dump()
    получает объект данных JSON и объект файла

    Построение карт с глобальными наборами данных: формат JSON 363
    и записывает данные в этот файл . Аргумент indent=4
    приказывает dump()
    фор- матировать данные с отступами, соответствующими структуре данных.
    Перейдите в каталог data и откройте файл readable_eq_data .json
    . Начальная часть выглядит так:
    readable_eq_data.json
    {
    "type": "FeatureCollection",

    "metadata": {
    "generated": 1550361461000,
    "url": "https://earthquake.usgs.gov/earthquakes/.../1.0_day.geojson",
    "title": "USGS Magnitude 1.0+ Earthquakes, Past Day",
    "status": 200,
    "api": "1.7.0",
    "count": 158
    },

    "features": [
    В первую часть файла включена секция с ключом "metadata"
    . По ней можно определить, когда файл был сгенерирован и где можно найти данные в интернете.
    Также в ней содержится понятный заголовок и количество землетрясений, вклю- ченных в файл. За этот 24-часовой период было зарегистрировано 158 землетря- сений.
    Структура файла geoJSON
    хорошо подходит для географических данных. Инфор- мация хранится в списке, связанном с ключом "features"
    . Так как в файле хра- нится информация о землетрясениях, эти данные имеют форму списка, в котором каждый элемент соответствует одному землетрясению. На первый взгляд структура кажется запутанной, но она весьма полезна. Например, геолог может сохранить в словаре столько информации о каждом землетрясении, сколько потребуется, а затем объединить все словари в один большой список.
    Рассмотрим словарь, представляющий одно землетрясение:
    readable_eq_data.json
    {
    "type": "Feature",

    "properties": {
    "mag": 0.96,

    "title": "M 1.0 - 8km NE of Aguanga, CA"
    },

    "geometry": {
    "type": "Point",
    "coordinates": [

    -116.7941667,

    33.4863333,
    3.22
    ]

    364 Глава 16 • Загрузка данных
    },
    "id": "ci37532978"
    },
    Ключ "properties"
    содержит подробную информацию о каждом землетрясении .
    Нас прежде всего интересует магнитуда каждого землетрясения, связанная с клю- чом "mag"
    . Также представляет интерес заголовок каждого землетрясения, содер- жащий удобную сводку магнитуды и координат .
    Ключ "geometry"
    помогает определить, где произошло землетрясение . Эта информация потребуется для географической привязки событий. Долгота x
    ‰
    ‰
    и широта  y
    для каждого землетрясения содержатся в списке, связанном с ключом "coordinates"
    Уровень вложенности в этом коде намного выше, чем мы использовали бы в своем коде, и если он покажется запутанным — не огорчайтесь; Python берет на себя большую часть сложности. В любой момент времени мы будем работать с одним или двумя уровнями. Мы начнем с извлечения словаря для каждого землетрясения, зарегистрированного за 24-часовой период.
    ПРИМЕЧАНИЕ В географических координатах часто сначала указывается широта, а затем долгота . Вероятно, эта система обозначений возникла из-за того, что люди обнаружили широту задолго до того, как была изобретена концепция долготы . Тем не менее во многих геопространственных библиотеках сначала указывается долгота, а по- том широта, потому что этот порядок соответствует системе обозначений (x, y), исполь- зуемой в математических представлениях . Формат geoJSON использует систему записи
    (долгота, широта), и если вы будете работать с другой библиотекой, очень важно за- ранее узнать, какую систему использует эта библиотека .
    Построение списка всех землетрясений
    Начнем с построения списка, содержащего всю информацию обо всех произошед- ших землетрясениях.
    eq_explore_data.py
    import json
    # Изучение структуры данных.
    filename = 'data/eq_data_1_day_m1.json'
    with open(filename) as f:
    all_eq_data = json.load(f)
    all_eq_dicts = all_eq_data['features']
    print(len(all_eq_dicts))
    Мы берем данные, ассоциированные с ключом 'features'
    , и сохраняем их в all_
    eq_dicts
    . Известно, что файл содержит данные около 158 землетрясений, а вывод подтверждает, что были прочитаны данные всех землетрясений из файла:
    158

    Построение карт с глобальными наборами данных: формат JSON 365
    Обратите внимание на то, каким коротким получился код. Аккуратно отформати- рованный файл readable_eq_data .json содержит более 6000 строк. Всего в нескольких строках кода мы прочитали все данные и сохранили их в списке Python. Теперь извлечем данные магнитуд по каждому землетрясению.
    Извлечение магнитуд
    Имея список, содержащий данные по всем землетрясениям, мы можем перебрать содержимое списка и извлечь всю необходимую информацию. В данном случае это будет магнитуда каждого землетрясения:
    eq_explore_data.py
    all_eq_dicts = all_eq_data['features']

    mags = []
    for eq_dict in all_eq_dicts:

    mag = eq_dict['properties']['mag']
    mags.append(mag)
    print(mags[:10])
    Создадим пустой список для хранения магнитуд, а затем переберем в цикле словарь all_eq_dicts
    . Внутри цикла каждое землетрясение представляется словарем eq_dict
    . Магнитуда каждого землетрясения хранится в секции 'properties'
    сло- варя с ключом 'mag'
    . Каждая магнитуда сохраняется в переменной mag и присо- единяется к списку mags
    Выведем первые 10 магнитуд, чтобы убедиться в том, что были получены правиль- ные данные:
    [0.96, 1.2, 4.3, 3.6, 2.1, 4, 1.06, 2.3, 4.9, 1.8]
    Затем мы извлечем данные местоположения (то есть координаты) для каждого землетрясения, а затем построим карту землетрясений.
    Извлечение данных местоположения
    Данные местоположения хранятся с ключом "geometry"
    . В словаре geometry при- сутствует ключ "coordinates"
    , первыми двумя значениями которого являются долгота и широта. Извлечение данных происходит следующим образом:
    eq_explore_data.py
    all_eq_dicts = all_eq_data['features']
    mags, lons, lats = [], [], []
    for eq_dict in all_eq_dicts:
    mag = eq_dict['properties']['mag']

    366 Глава 16 • Загрузка данных

    lon = eq_dict['geometry']['coordinates'][0]
    lat = eq_dict['geometry']['coordinates'][1]
    mags.append(mag)
    lons.append(lon)
    lats.append(lat)
    print(mags[:10])
    print(lons[:5])
    print(lats[:5])
    Для долгот и широт создаются пустые списки (
    lons и lats
    ). Выражение eq_
    dict['geometry']
    обращается к словарю, представляющему элемент geometry данных землетрясения
    (1)
    . Второй ключ 'coordinates'
    извлекает список значений, связанных с ключом 'coordinates'
    . Наконец, индекс 0 запрашивает первое значе- ние в списке координат, соответствующее долготе землетрясения.
    При выводе первых пяти долгот и широт становится видно, что данные были из- влечены правильно:
    [0.96, 1.2, 4.3, 3.6, 2.1, 4, 1.06, 2.3, 4.9, 1.8]
    [-116.7941667, -148.9865, -74.2343, -161.6801, -118.5316667]
    [33.4863333, 64.6673, -12.1025, 54.2232, 35.3098333]
    С этими данными можно переходить к нанесению координат землетрясений на географическую карту.
    Построение карты мира
    На основании всей информации, собранной к настоящему моменту, можно по- строить простую карту мира. И хотя первая версия будет выглядеть убого, нужно убедиться в том, что информация отображается правильно, прежде чем сосредото- читься на стиле и визуальном оформлении. Исходная карта выглядит так:
    eq_world_map.py
    import json

    from plotly.graph_objs import Scattergeo, Layout from plotly import offline for eq_dict in all_eq_dicts:
    # Нанесение данных на карту.

    data = [Scattergeo(lon=lons, lat=lats)]

    my_layout = Layout(title='Global Earthquakes')

    fig = {'data': data, 'layout': my_layout}
    offline.plot(fig, filename='global_earthquakes.html')

    Построение карт с глобальными наборами данных: формат JSON
    1   ...   35   36   37   38   39   40   41   42   ...   52


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