Расстояние между двумя группами значений в массиве numpy - PullRequest
2 голосов
/ 03 мая 2019

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

У меня есть 2 переменные: 'Root zone', также известная как RTZ, и 'Tree cover', также известная как TC, которые представляют собой массив значений 250x186 (которые в основном являются сетками с каждой сеткой, имеющей определенное значение). Значения в TC варьируются от 0 до 100. Размер каждой сетки составляет 0,25 градуса (может быть полезно для понимания расстояния).

Моя проблема в том, что «я хочу вычислить расстояние каждого значения TC в диапазоне от 50 до 100 (то есть каждое значение значения TC больше 50 в каждом lat и lon) от точек, где находится ближайший TC в диапазоне от 0 до 30 (менее 30). "

Просто учтите, что мы не смотрим на np.nan часть TC. Таким образом, белая часть в TC также белая в RZS. enter image description here

Я хочу создать двумерную диаграмму рассеяния, ось X которой обозначает «расстояние 50–100 TC от 0–30 значений», а ось Y обозначает «RZS из этих 50- 100 TC баллов '. Приведенный выше рисунок может прояснить ситуацию.

Я надеюсь, что мог бы предоставить какой-нибудь код для этого, но я даже не в состоянии начать на расстоянии. Пожалуйста, предоставьте любые предложения о том, как мне поступить с этим.

Давайте рассмотрим пример: Если вы посмотрите на x: 70 и y: 70, можно увидеть множество точек со значениями от 0 до 30 дерева, охватывающих весь набор данных. Но мне нужно только расстояние от ближайшего значения до моей точки, которое падает между 0-30.

1 Ответ

2 голосов
/ 05 мая 2019

Следующий код может работать со случайными примерами данных:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
# Create some completely random data, and include an area of NaNs as well
rzs = np.random.uniform(0, 100, size=(250, 168))
tc = np.random.lognormal(3.0, size=(250, 168))
tc = np.clip(tc, 0, 100)
rzs[60:80,:] = np.nan
tc[60:80,:] = np.nan

plt.subplot(2,2,1)
plt.imshow(rzs)
plt.colorbar()
plt.subplot(2,2,2)
plt.imshow(tc)
plt.colorbar()

enter image description here

Теперь выполним реальную работу:

# Select the indices of the low- and high-valued points
# This will results in warnings here because of NaNs;
# the NaNs should be filtered out in the indices, since they will 
# compare to False in all the comparisons, and thus not be 
# indexed by 'low' and 'high'
low = (tc >= 0) & (tc <= 30)
high = (tc >= 50) & (tc <= 100)
# Get the coordinates for the low- and high-valued points,
# combine and transpose them to be in the correct format
y, x = np.where(low)
low_coords = np.array([x, y]).T
y, x = np.where(high)
high_coords = np.array([x, y]).T

# We now calculate the distances between *all* low-valued points, and *all* high-valued points.
# This calculation scales as O^2, as does the memory cost (of the output), 
# so be wary when using it with large input sizes.
from scipy.spatial.distance import cdist, pdist
distances = cdist(low_coords, high_coords)

# Now find the minimum distance along the axis of the high-valued coords, 
# which here is the second axis.
# Since we also want to find values corresponding to those minimum distances, 
# we should use the `argmin` function instead of a normal `min` function.
indices = distances.argmin(axis=1)
mindistances = distances[np.arange(distances.shape[0]), indices]
minrzs = rzs.flatten()[indices]

plt.scatter(mindistances, minrzs)

enter image description here

Результирующий график выглядит немного странно, поскольку существуют довольно дискретные расстояния из-за сетки (1, sqrt (1 ^ 1 + 1 ^ 1),2, sqrt (1 ^ 1 + 2 ^ 2), sqrt (2 ^ 2 + 2 ^ 2), 3, sqrt (1 ^ 1 + 3 ^ 2), ...);это связано с тем, что оба значения TC распределены случайным образом, и, таким образом, низкие значения могут в конечном итоге непосредственно примыкать к высоким значениям (и поскольку мы ищем минимальные расстояния, большинство точек на графике предназначены для этих случаев).Вертикальное распределение объясняется тем, что значения RZS были равномерно распределены между 0 и 100.
Это просто результат входных данных примера, который не слишком отражает реальные данные.

...