У меня есть 3D-массив (z, y, x)
с shape=(92, 4800, 4800)
, где каждое значение вдоль axis 0
представляет собой другой момент времени. Приобретение значений во временном домене не удалось в нескольких случаях, вызвав некоторые значения np.NaN
. В других случаях значения не были получены, и все значения вдоль z
составляют np.NaN
.Быстрая 1D линейная np.NaN интерполяция над большой 3D-матрицей
Каков наиболее эффективный способ использования линейной интерполяции для заполнения np.NaN
по адресу axis 0
без учета экземпляров, где все значения равны np.NaN
?
Вот рабочий пример того, что я делаю, который использует pandas
wrapper для scipy.interpolate.interp1d
. Это занимает около 2 секунд на каждый фрагмент исходного набора данных, что означает, что весь массив обрабатывается в 2.6 часа. Примерный набор данных с уменьшенным размером занимает около 9,5 секунд.
import numpy as np
import pandas as pd
# create example data, original is (92, 4800, 4800)
test_arr = np.random.randint(low=-10000, high=10000, size=(92, 480, 480))
test_arr[1:90:7, :, :] = -32768 # NaN fill value in original data
test_arr[:, 1:90:6, 1:90:8] = -32768
def interpolate_nan(arr, method="linear", limit=3):
"""return array interpolated along time-axis to fill missing values"""
result = np.zeros_like(arr, dtype=np.int16)
for i in range(arr.shape[1]):
# slice along y axis, interpolate with pandas wrapper to interp1d
line_stack = pd.DataFrame(data=arr[:,i,:], dtype=np.float32)
line_stack.replace(to_replace=-37268, value=np.NaN, inplace=True)
line_stack.interpolate(method=method, axis=0, inplace=True, limit=limit)
line_stack.replace(to_replace=np.NaN, value=-37268, inplace=True)
result[:, i, :] = line_stack.values.astype(np.int16)
return result
Производительность на моей машине с набором данных, например:
%timeit interpolate_nan(test_arr)
1 loops, best of 3: 9.51 s per loop
Edit:
я должен уточнить, что код производит мой ожидаемый результат. Вопрос в том, как я могу оптимизировать этот процесс?
Запуск примера занимает около 9,5 секунд на моей машине, но форма test_arr - '(92, 480, 480)'. Если вы увеличите его до размера реального набора данных '(92, 4800, 4800)' и распространите его с помощью более * NaN *, этот метод займет значительно больше времени. – Kersten