Вдохновение для этого проекта началось в начале этого месяца. Я был на небольшом семейном отдыхе в Mt. Маунгануи . Из множества занятий мы начали восхождение на Мауао.
На вершине вас встретит не только потрясающий вид на прибрежный городок, но и высокое необычное сооружение, известное как геодезический указатель, а точнее триггерная станция.
Ниже приведена табличка с точной триггерной станцией, расположенной на вершине Мауао:
И это вдохновило меня на этот проект. Имея полный банк данных этих маркеров, их местоположения и высоты, можем ли мы нанести их на карту и раскрасить по высоте?
И это то, что мы планируем сделать в следующем проекте.
Вот ссылка на Github для кода.
Очки обучения
Прежде чем мы застрянем, мы рассмотрим некоторые обучающие моменты, которые мы расскажем в этом посте.
- Как использовать
pandas
для загрузки.csv
данных - Использование
matplotlib
и его функциональность pandas
метод группировки и агрегирование- Использование
seaborn
в качестве метода построения графиков в сочетании сmatplotlib
Как получить доступ к данным
На веб-сайте Координатов хранится большая часть геопространственных данных Новой Зеландии. Нам потребуется создать учетную запись для доступа к данным для этого проекта. К счастью, это не стоит ни цента.
Мы можем искать NZ Geodetic Vertical Marks. Эти данные собраны участниками сайта Land Information New Zealand. Выбор вертикальных меток дает нам высоту в определенном формате.
Когда дело доходит до высоты, простое измерение не так просто.
Не вдаваясь в подробности, вертикальные опорные точки напоминают так называемые нормальные ортометрические высоты. Это то, что нам больше всего известно как высота над уровнем моря. Нормально-ортометрическая высота на самом деле является средней / средней высотой на уровне моря (поскольку уровень моря может меняться с приливом).
Это противоположно эллипсоидальной высоте, которая аппроксимирует Землю как эллипсоид и использует ее как точку отсчета.
На сайте LINZ это более подробно описано.
Импортируйте библиотеки и загружайте данные
import pandas as pd
import numpy as np
#import random as r
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import matplotlib.colors as colors
import matplotlib.cm as cmx
from matplotlib.lines import Line2D
import seaborn as sns
%matplotlib inline
Здесь мы можем использовать !
, который вызывает магическую функцию. В следующем случае мы используем команду linux ls
для вывода списка файлов в каталоге ./files
.
Мы будем использовать .csv
файлы и загрузить их в фреймворк pandas.
# find the name of the .csv file containing the data !ls ./files
nz-geodetic-vertical-marks.csv nz-geodetic-vertical-marks.txt nz-geodetic-vertical-marks.csvt nz-geodetic-vertical-marks.vrt nz-geodetic-vertical-marks.prj nz-geodetic-vertical-marks.xml
# load into dataframe geomarks = pd.read_csv('files/nz-geodetic-vertical-marks.csv') geomarks
Здесь у нас есть данные, загруженные в фреймворк pandas. Давайте еще раз исследуем данные.
# explore the data more geomarks.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 105583 entries, 0 to 105582 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 WKT 105583 non-null object 1 id 105583 non-null int64 2 nod_id 105583 non-null int64 3 geodetic_code 105583 non-null object 4 current_mark_name 105583 non-null object 5 description 73350 non-null object 6 mark_type 105583 non-null object 7 beacon_type 93424 non-null object 8 mark_condition 87315 non-null object 9 order 105583 non-null object 10 land_district 105295 non-null object 11 normal_orthometric_height 105583 non-null float64 12 coordinate_system 105583 non-null object 13 shape_X 105583 non-null float64 14 shape_Y 105583 non-null float64 dtypes: float64(3), int64(2), object(10) memory usage: 12.1+ MB
Изучение данных
Мы видим, что всего 105 582 записи.
Важными характеристиками (входными переменными) являются shape_X
, shape_Y
, которые напоминают долготу и широту, и normal_orthometric_height
, обозначающие высоту. Все они учтены без пропущенных значений.
Используя shape_X
и shape_Y
, мы можем нарисовать это, чтобы представить географическое пространство. Вероятно, это уже происходило бесчисленное количество раз, но когда я узнал об этом в книге Орелиена Жерона Hands On Machine Learning, 2nd edition, я просто поразился!
mapNZ = geomarks.plot(kind='scatter', x='shape_X', y='shape_Y', figsize=(10,10))
ax = plt.axis('off')
Выглядит знакомо?
Это Новая Зеландия!
Столько маркеров, если быть точным, 105 582. Итак, уменьшим размер маркеров. Мы можем изменить параметры:
alpha
- это непрозрачность маркераs
- размер маркера
и это позволит нам намного легче видеть отдельные маркеры.
mapNZ = geomarks.plot(kind='scatter', x='shape_X', y='shape_Y',
figsize=(10,10), alpha=0.8, s=0.2)
ax = plt.axis('off')
Теперь мы можем применить цвет в зависимости от высоты по вертикали.
Вот важные параметры:
c
- это цвета точекcmap
- предоставляет цветовую схему; мы будем использоватьjet
Использование этих параметров создаст новое измерение нашего графика.
Мы также изменили размер маркеров по высоте, чтобы подчеркнуть этот атрибут. Делим на 100 для очевидного масштабирования.
mapNZ = geomarks.plot(kind='scatter', x='shape_X', y='shape_Y', figsize=(10,8), s=geomarks['normal_orthometric_height']/100, c='normal_orthometric_height', cmap=plt.get_cmap('jet'), colorbar=True) ax = plt.axis('off')
/home/shivan/miniconda3/envs/shivan_env/lib/python3.7/site-packages/matplotlib/collections.py:922: RuntimeWarning: invalid value encountered in sqrt scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
Вы можете заметить, что нижние точки заглушают более высокие, несмотря на то, что размер маркера варьируется по высоте по вертикали.
Когда мы исследуем вертикальные высоты более подробно, мы видим, что большинство из них находится на нижнем конце. График показывает, что данные тяжелые.
heights = geomarks['normal_orthometric_height'] heights.describe()
count 105583.000000 mean 176.935780 std 280.401109 min -34.179500 25% 17.300748 50% 56.743200 75% 223.130634 max 3029.710448 Name: normal_orthometric_height, dtype: float64
height_graphs = heights.plot(kind='hist', bins=50, figsize=(15,5), title='Histogram of Heights')
Что мы можем сделать, так это изменить альфа через cmap. Мы берем cmap и меняем альфа-канал, чтобы более холодные цвета ассоциировались с более низкими вертикальными высотами, а также имели более низкие альфа по сравнению с более теплыми цветами с большими высотами.
x = geomarks['shape_X'] y = geomarks['shape_Y'] c = geomarks['normal_orthometric_height'] s = geomarks['normal_orthometric_height']/100 cmap = plt.cm.jet my_cmap = cmap(np.arange(cmap.N)) my_cmap[:, -1] = np.linspace(0, 1, cmap.N) my_cmap = ListedColormap(my_cmap) plt.figure(figsize=(10,8)) plt.scatter(x, y, c=c, s=s, cmap=my_cmap) plt.title("Map of New Zealand") ax = plt.axis('off') cbar = plt.colorbar()
/home/shivan/miniconda3/envs/shivan_env/lib/python3.7/site-packages/matplotlib/collections.py:922: RuntimeWarning: invalid value encountered in sqrt scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
И вот у нас есть карта, которую мы намеревались создать.
Но не будем останавливаться на достигнутом! Давайте посмотрим на другие аспекты данных.
Вы можете видеть, что темно-красное пятно - самое высокое из всех маркеров. Это гора Аспиринг, которая не является самой высокой вершиной Новой Зеландии, в отличие от Аораки или горы Кук.
# Top highest geodetic markers in New Zealand
geomarks.sort_values(by='normal_orthometric_height', ascending=False).head()
Дальнейшее изучение данных
Давайте посмотрим маркеры по районам. Затем мы можем нанести эти данные на гистограмму.
geomarks['land_district'] = geomarks['land_district'].astype('str') by_district = geomarks['land_district'].value_counts() by_district
North Auckland 24125 South Auckland 15496 Wellington 12595 Canterbury 11741 Nelson 9129 Otago 8326 Gisborne 5765 Southland 4847 Hawkes Bay 4427 Taranaki 3092 Marlborough 2884 Westland 2868 nan 288 Name: land_district, dtype: int64
Мы видим, что на самом деле есть некоторые скрытые nan
. NaN означает« не число ». Он представляет собой пустые данные.
Мы можем выявить эти nan
, преобразовав тип столбца в строку. Нам нужно отбросить их для следующей обработки.
geomarks = geomarks[geomarks['land_district']!='nan'] by_district = geomarks['land_district'].value_counts() by_district
North Auckland 24125 South Auckland 15496 Wellington 12595 Canterbury 11741 Nelson 9129 Otago 8326 Gisborne 5765 Southland 4847 Hawkes Bay 4427 Taranaki 3092 Marlborough 2884 Westland 2868 Name: land_district, dtype: int64
Здесь nan
были удалены
by_district.plot(kind='bar', title='Number of Marks by district')
plt.show()
Затем давайте посмотрим на среднюю высоту каждого района. Мы делаем это с помощью groupby
и agg
или агрегирования. Мы также удалим дополнительные столбцы, чтобы облегчить чтение.
district_group = geomarks.groupby('land_district') # groups data by district
district_means = district_group.agg(['mean', 'sem']) # 'sem' means standard error, sem = std / n ** (1/2)
district_means = district_means.drop(['id', 'nod_id', 'shape_X', 'shape_Y'], axis=1) # dropping extra columns for readability
district_means = district_means.sort_values(by=('normal_orthometric_height', 'mean'), ascending=False)
district_means
x = district_means[('normal_orthometric_height', 'mean')]
err = district_means[('normal_orthometric_height', 'sem')]
# notice how we call the tuple for a hierarchical column
plt.figure(figsize=(10,5))
plt.barh(y=x.index, width=x.values, xerr=err, capsize=5)
plt.title('Mean Heights per District')
plt.xlabel('Mean of Height')
plt.ylabel('District')
plt.show()
Мы видим, что у Отаго в среднем самые высокие маркеры.
Вернемся к карте Новой Зеландии. Что мы собираемся сделать иначе, так это то, что мы собираемся наносить точки, но использовать категориальные цвета. Цвета будут зависеть от района. И цвета будут ранжироваться по средней высоте этого района.
Мы будем использовать цветовую палитру seaborn
, чтобы создать цветовую метку, в которой будут равномерно распределены значения RGB.
Мы также должны создать собственную легенду, используя Lin2D
x = geomarks['shape_X'] y = geomarks['shape_Y'] s = geomarks['normal_orthometric_height'] / 500 plt.figure(figsize=(10,10)) colour_labels = list(district_means.index) # turns districts into a list rgb_values = sns.color_palette('coolwarm_r', len(colour_labels)) # use seaborn to create colours, # the number is based on the number of districts colour_map = dict(zip(colour_labels, rgb_values)) # create a dict of district as keys and colours as values legend_elements = [Line2D([0], [0], marker='o', color='w', markersize=8, markerfacecolor=colour_map[label]) for label in colour_map] # creating a legend NZ_d_map = plt.scatter(x, y, alpha=0.5, s=s, c=geomarks['land_district'].map(colour_map)) leg_ = plt.legend(legend_elements, colour_labels) ax = plt.axis('off') title_ = plt.title('Plot of Geodetic Markers coloured by district')
/home/shivan/miniconda3/envs/shivan_env/lib/python3.7/site-packages/matplotlib/collections.py:922: RuntimeWarning: invalid value encountered in sqrt scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
И вот она, карта Новой Зеландии с цветовой кодировкой, основанная на земельном округе, ранжированном по средней высоте его маркеров.
Заключение
Прогулки и праздники отлично подходят для создания идей. Простая прогулка на гору натолкнула на мысль создать карты на основе высот геодезических маркеров Новой Зеландии.
Мы использовали различные методы - благодаря библиотекам Python _53 _, _ 54_, matplotlib
и seaborn
для работы с данными из Координатов и Земельной информации Новой Зеландии (LINZ).
Мы использовали эти данные для создания карты Новой Зеландии с цветовой кодировкой на основе нормальных ортометрических высот геодезических маркеров. В дополнение к этому мы создали еще одну карту на основе земельных участков, и она была ранжирована по средней высоте каждого района.
Я надеюсь, что вы нашли это полезным, и я хотел бы услышать, что еще можно сделать с этими данными. Пожалуйста, поделитесь этим со всеми, кто, по вашему мнению, сочтет это интересным.
использованная литература
- Mount Maunganui - Что посмотреть и чем заняться - Северный остров | Новая Зеландия. (нет данных). Www.Newzealand.com. Https://www.newzealand.com/int/mount-maunganui/
- Гора Маунгануи (гора). (2020, 20 ноября). Википедия. Https://en.wikipedia.org/wiki/Mount_Maunganui_(mountain)
- Координаты - Платформа данных Земли. (нет данных). Koordinates.com. Https://koordinates.com/
- Новозеландские геодезические вертикальные метки. (нет данных). Koordinates.com. Получено 11 декабря 2020 г. с сайта https://koordinates.com/from/data.linz.govt.nz/layer/50784/.
- Земельная информация Новой Зеландии (LINZ). (нет данных). Земельная информация Новой Зеландии (LINZ). Https://www.linz.govt.nz/
- Вертикальные опорные точки. (нет данных). Земельная информация Новой Зеландии (LINZ). Получено 11 декабря 2020 г. с сайта https://www.linz.govt.nz/data/geodetic-system/datums-projection-and-heights/vertical-datums.
- (2019). Глава 2: Проект сквозного машинного обучения [Обзор главы 2: Проект сквозного машинного обучения]. В руках по машинному обучению (стр. 35–84). О'Рейли.
- Python R. Plot With Pandas: Визуализация данных Python для начинающих - Настоящий Python. realpython.com. По состоянию на 11 декабря 2020 г. https://realpython.com/pandas-plot-python/
- Как нормализовать столбец Pandas DataFrame. CodeSpeedy. Опубликовано 19 февраля 2020 г. Проверено 11 декабря 2020 г. https://www.codespeedy.com/normalize-a-pandas-dataframe-column/
- Абдишакур. (2020, 29 апреля). Как сделать карты значений по альфа-версии в Python. Получено с веб-сайта Medium: https://towardsdatascience.com/how-to-make-value-by-alpha-maps-in-python-484722160490
- Библиотека анализа данных Python - pandas: Библиотека анализа данных Python. Pydata.org. Опубликовано 2018 г. https://pandas.pydata.org/
- Python Pandas - GroupBy - Tutorialspoint. Www.tutorialspoint.com. По состоянию на 14 декабря 2020 г. https://www.tutorialspoint.com/python_pandas/python_pandas_groupby.htm
- Цвет точечной диаграммы Matplotlib по категориям в Python. каноки. Опубликовано 30 августа 2020 г. Проверено 15 декабря 2020 г. https://kanoki.org/2020/08/30/matplotlib-scatter-plot-color-by-category-in-python/
- Составление собственных легенд - документация Matplotlib 3.2.1. matplotlib.org. По состоянию на 24 декабря 2020 г. https://matplotlib.org/3.2.1/gallery/text_labels_and_annotations/custom_legends.html
- Гора Аспиринг / Тититея. Википедия. Опубликовано 12 августа 2020 г. Проверено 24 декабря 2020 г. https://en.wikipedia.org/wiki/Mount_Aspiring_/_Tititea