#python #matplotlib #plot #seaborn #haversine
#python #matplotlib #график #seaborn #haversine
Вопрос:
Я пытаюсь найти наилучший способ построения некоторых данных. В принципе, у меня есть файл данных, в котором есть столбцы latitude, longitude, depth, sample_ID, Group_ID. Я хотел бы сгенерировать 2-мерную точечную диаграмму, где y — глубина, а x — расстояние в км с севера на юг (или рассчитать расстояния в разрезе относительно первой станции, отобранной в указанной ориентации), аналогично карте в стиле ODV, подобной приведенной ниже:
ОБНОВЛЕНО
Я хотел добавить немного больше информации к моему первоначальному вопросу. После еще нескольких поисков и тестирования я нашел возможное решение в R, используя пакет geosphere и функцию distGeo для преобразования моих координат в расстояние в км, которое затем можно отобразить. (https://www.rdocumentation.org/packages/geosphere/versions/1.5-10/topics/distGeo )
Если кто-нибудь знает способ python сделать это, это было бы здорово!
ОБНОВЛЕНО
Однако ODV не позволяет мне выполнять необходимые настройки. Я хотел бы сгенерировать такой график, где я могу указать переменную метаданных для раскрашивания точек. Чтобы быть более конкретным по столбцу group_ID в моем файле данных, который показан в примере моего файла ниже.
Latitude Longitude Depth_m Sample_ID Group_ID
49.7225 -42.4467 10 S1 1
49.7225 -42.4467 50 S2 1
49.7225 -42.4467 75 S3 1
49.7225 -42.4467 101 S4 1
49.7225 -42.4467 152 S5 1
49.7225 -42.4467 199 S6 1
46.312 -39.658 10 S7 2
46.312 -39.658 49 S8 2
46.312 -39.658 73 S9 2
46.312 -39.658 100 S10 2
46.312 -39.658 153 S11 2
46.312 -39.658 198 S12 2
Это доставляло мне много проблем, пытаясь понять это. Я рассчитал расстояние между координатами, используя вычисление haversine, но как только я туда доберусь, я не уверен, как использовать эти расстояния для включения в точечную диаграмму. Это то, что у меня есть до сих пор:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
#import haversine as hs
from math import radians
from sklearn.neighbors import DistanceMetric
df=pd.read_csv("locations.csv",sep="t",index_col="Sample_ID")
#plt.scatter(df['Latitude'], df['Depth_m'])
#plt.show()
df['Latitude'] = np.radians(df['Latitude'])
df['Longitude'] = np.radians(df['Longitude'])
dist = DistanceMetric.get_metric('haversine')
x = dist.pairwise(np.unique(df[['Latitude','Longitude']].to_numpy(),axis=0))*6373
print(x)
Этот код выдает мне матрицу расстояний для моих координат, но я, честно говоря, не могу понять, как это сделать и перенести на точечную диаграмму, которая устанавливает ось x с севера на юг. Тем более, что существует несколько глубин с одной и той же координатой, которые необходимо учитывать. Любая помощь в построении графика очень ценится!
Комментарии:
1. Что вы хотите по оси x конкретно для всех xticks? Для вывода вашего примера я получаю:
[[ 0. 432.30988584] [432.30988584 0. ]]
2. Итак, теоретически я хочу, чтобы на оси X точка ‘0’ оси начиналась с самой северной координаты, которая должна быть (49.7225, -42.4467), а затем остальные координаты будут вычисляться как расстояние от этой координаты в км. Возможно, мне потребуется пересмотреть мои вычисления haversine. Текущая переменная x была матрицей расстояний, но может быть проще использовать функцию haversine, которая должна быть просто haversin(loc1, loc2)
Ответ №1:
Для вычисления расстояния вы можете использовать пакет geopy, в частности geopy.distance.geodesic(), для вычисления расстояния по дуге, предполагая конкретный эллипсоид (например, WGS84).
Чтобы сгенерировать график, аналогичный описанному вами, вы можете использовать функциональность диаграммы рассеяния библиотеки matplotlib, в частности matplotlib.pyplot.scatter() .
Приведенный ниже пример кода поможет вам выполнить как вычисление расстояния (расстояние от некоторой эталонной широты / длины до другой широты / длины… это не обязательно компонент N-S, но его достаточно легко вычислить). А также как сгенерировать точечную диаграмму, используя ваше поле Group_ID, чтобы раскрасить точки, используя два метода.
import matplotlib.pyplot as plt
import geopy
import pandas as pd
# Load your sample data to a Pandas DataFrame where each column corresponds to
# 'Latitude', 'Longitude', 'Depth_m', 'Sample_ID', 'Group_ID'
datafile = r'<path to a file containing your data>'
df = pd.read_csv(datafile)
# Defining one end of our arc to calculate distance along (arbitrarily taking
# the first point in the example data as the reference point).
ref_point = (df['Latitude'].iloc[0], df['Longitude'].iloc[0])
# Loop over each sample location calculating the distance along the arc using
# pygeo.distance.geodesic function.
dist = []
for i in range(len(df)):
cur_point = (df['Latitude'].iloc[i], df['Longitude'].iloc[i])
cur_geodesic = geopy.distance.geodesic(ref_point, cur_point)
cur_dist = cur_geodesic.km
dist.append(cur_dist)
# Add computed distances to the df DataFrame as column 'Distance_km'
df['Distance_km'] = dist
# Create a matplotlib figure and add two axes for plotting
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
# Example 1: of creating a scatter plot using the calculated distance field and
# colouring the points using a numeric field (i.e. Group_ID in this case is numeric)
pts = ax1.scatter(df['Distance_km'], df['Depth_m'], s=30, c=df['Group_ID'], cmap=plt.cm.jet)
plt.colorbar(pts, ax=ax1)
ax1.set_xlabel('Arc Distance from Reference Point (km)')
ax1.set_ylabel('Depth (m)')
ax1.set_title('Colouring Points by a Numeric Field')
ax1.invert_yaxis()
ax1.grid(True)
# Example of creating basically the same scatter plot as above but handling the
# case of non-numeric values in the field to be used for colour (e.g. imagine
# wanting to the the Sample_ID field instead)
groups = list(set(df['Group_ID'])) # get a list of the unique Group_ID values
for gid in groups:
df_tmp = df[df['Group_ID'] == gid]
ax2.scatter(df_tmp['Distance_km'], df_tmp['Depth_m'], s=30, label=gid)
ax2.legend(loc='upper center', title='Legend')
ax2.set_xlabel('Arc Distance from Reference Point (km)')
ax2.set_ylabel('Depth (m)')
ax2.set_title('Colouring Points with Using Categorical Values')
ax2.invert_yaxis()
ax2.grid(True)
fig.tight_layout()
plt.show()
Ответ №2:
Я не уверен, что вы пытаетесь сделать с расстоянием, но концептуально вам нужно получить вывод x в свой фрейм данных в виде нового столбца, как я это сделал.Что касается наличия другого цвета для групп, я бы использовал seaborn
для этого, поскольку у них есть hue
параметр. Пожалуйста, ознакомьтесь с выводом ниже вашей первой диаграммы рассеяния и попыткой того, что вы пытаетесь сделать со своей второй диаграммой рассеяния:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from math import radians
from sklearn.neighbors import DistanceMetric
import seaborn as sns
fig, ax = plt.subplots(nrows=2)
sns.scatterplot(data=df, x='Latitude', y='Depth_m', hue='Group_ID', ax=ax[0])
df['Latitude'] = np.radians(df['Latitude'])
df['Longitude'] = np.radians(df['Longitude'])
dist = DistanceMetric.get_metric('haversine')
df['Distance'] = (dist.pairwise(df[['Latitude','Longitude']].to_numpy())*6373)[0]
sns.scatterplot(data=df, x='Distance' , y='Depth_m', hue='Group_ID', ax=ax[1])
plt.show()
Комментарии:
1. Спасибо за предоставление этого! Возможно, это не тождественно тому, что я искал, но это очень полезная альтернатива. Проведя еще немного исследований, я могу просто переключиться на R, потому что у них есть функция distGeo ( rdocumentation.org/packages/geosphere/versions/1.5-10/topics / … ), который, по-видимому, производит вычисления координат по оси x, которые я пытался выполнить.
2. На самом деле, теперь, когда я перешел к этому построчно, чтобы понять код, я действительно думаю, что это правильное решение!
3. @eric excellent, пожалуйста, примите в качестве ответа, нажав на галочку 🙂 Спасибо!