У меня есть некоторые экспериментальные данные, которые существуют так:
x = array([1, 1.12, 1.109, 2.1, 3, 4.104, 3.1, ...])
y = array([-9, -0.1, -9.2, -8.7, -5, -4, -8.75, ...])
z = array([10, 4, 1, 4, 5, 0, 1, ...])
Если это удобно, мы можем предположить, что данные существуют в виде 3D-массива или даже панды DataFrame
:
df = pd.DataFrame({'x': x, 'y': y, 'z': z})
Интерпретация заключается в том, что для каждой позиции x[i], y[i]
значение некоторой переменной равно z[i]
. Они отбираются неравномерно, поэтому некоторые части будут иметь "плотную выборку" (например, от 1 до 1,2 в x
), а другие - очень разреженные (например, от 2 до 3 в x
). Из-за этого я не могу просто бросить их в pcolormesh
или contourf
.
Вместо этого я хотел бы сделать повторную выборку x
и y
равномерно с некоторым фиксированным интервалом, а затем агрегировать значения z
. Для моих нужд z
можно суммировать или усреднить, чтобы получить значимые значения, так что это не проблема. Моя наивная попытка была такой:
X = np.arange(min(x), max(x), 0.1)
Y = np.arange(min(y), max(y), 0.1)
x_g, y_g = np.meshgrid(X, Y)
nx, ny = x_g.shape
z_g = np.full(x_g.shape, np.nan)
for ix in range(nx - 1):
for jx in range(ny - 1):
x_min = x_g[ix, jx]
x_max = x_g[ix + 1, jx + 1]
y_min = y_g[ix, jx]
y_max = y_g[ix + 1, jx + 1]
vals = df[(df.x >= x_min) & (df.x < x_max) &
(df.y >= y_min) & (df.y < y_max)].z.values
if vals.any():
z_g[ix, jx] = sum(vals)
Это работает, и я получаю желаемый результат с plt.contourf(x_g, y_g, z_g)
, но это МЕДЛЕННО! У меня есть ~20 тыс. отсчетов, которые я затем разделяю на ~800 отсчетов по x и ~500 отсчетов по y, что означает, что цикл for имеет длину 400 тыс.
Есть ли способ векторизовать/оптимизировать это? Еще лучше, если есть какая-то функция, которая уже это делает!
(Также помечаю это как MATLAB, потому что синтаксис между numpy/MATLAB очень похож, и у меня есть доступ к обоим программам.)