Interpolation multivariée de spline en python / scipy?
Existe-t-il un module de bibliothèque ou un autre moyen simple d'implémenter l'interpolation multivariée spline en python?
spécifiquement, j'ai un ensemble de données scalaires sur une grille tridimensionnelle régulièrement espacée que je dois interpoler à un petit nombre de points dispersés dans le domaine. Pour deux dimensions, j'ai utilisé scipy.interpoler.RectBivariateSpline , et je suis essentiellement à la recherche d'une extension de cette à données tridimensionnelles.
les routines d'interpolation n-dimensionnelle que j'ai trouvées ne sont pas assez bonnes: je préférerais splines plutôt que LinearNDInterpolator pour la douceur, et j'ai beaucoup trop de points de données (souvent plus d'un million) pour, par exemple, une fonction de base radiale pour fonctionner.
si quelqu'un connaît une bibliothèque python qui peut faire cela, ou peut-être une dans une autre langue que je pourrais appeler ou port, je l'apprécierais vraiment.
2 réponses
si je comprends bien votre question, vos données d ' "observation" sont régulièrement mises en grille?
si oui, scipy.ndimage.map_coordinates
fait exactement ce que tu veux.
c'est un peu difficile à comprendre à la première passe, mais essentiellement, vous lui donnez juste une séquence de coordonnées que vous voulez interpoler les valeurs de la grille à en pixel/voxel/n-Dimensions-coordonnées de l'index.
comme exemple 2D:
import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt
# Note that the output interpolated coords will be the same dtype as your input
# data. If we have an array of ints, and we want floating point precision in
# the output interpolated points, we need to cast the array as floats
data = np.arange(40).reshape((8,5)).astype(np.float)
# I'm writing these as row, column pairs for clarity...
coords = np.array([[1.2, 3.5], [6.7, 2.5], [7.9, 3.5], [3.5, 3.5]])
# However, map_coordinates expects the transpose of this
coords = coords.T
# The "mode" kwarg here just controls how the boundaries are treated
# mode='nearest' is _not_ nearest neighbor interpolation, it just uses the
# value of the nearest cell if the point lies outside the grid. The default is
# to treat the values outside the grid as zero, which can cause some edge
# effects if you're interpolating points near the edge
# The "order" kwarg controls the order of the splines used. The default is
# cubic splines, order=3
zi = ndimage.map_coordinates(data, coords, order=3, mode='nearest')
row, column = coords
nrows, ncols = data.shape
im = plt.imshow(data, interpolation='nearest', extent=[0, ncols, nrows, 0])
plt.colorbar(im)
plt.scatter(column, row, c=zi, vmin=data.min(), vmax=data.max())
for r, c, z in zip(row, column, zi):
plt.annotate('%0.3f' % z, (c,r), xytext=(-10,10), textcoords='offset points',
arrowprops=dict(arrowstyle='->'), ha='right')
plt.show()
pour ce faire en n-dimensions, nous avons juste besoin de passer dans les tableaux de taille appropriée:
import numpy as np
from scipy import ndimage
data = np.arange(3*5*9).reshape((3,5,9)).astype(np.float)
coords = np.array([[1.2, 3.5, 7.8], [0.5, 0.5, 6.8]])
zi = ndimage.map_coordinates(data, coords.T)
en ce qui concerne la mise à l'échelle et l'utilisation de la mémoire, map_coordinates
créera une copie filtrée du tableau si vous utilisez un ordre > 1 (c.-à-d. pas d'interpolation linéaire). Si vous voulez juste pour interpoler à un très petit nombre de points, c'est un assez grand frais généraux. Il n'a pas augmenter avec le nombre de points que vous voulez interpoler à, Cependant. Tant que vous avez assez de RAM pour une seule copie temporaire de votre tableau de données d'entrée, tout ira bien.
si vous ne pouvez pas stocker une copie de vos données en mémoire, vous pouvez soit a) spécifier prefilter=False
et order=1
et utiliser l'interpolation linéaire, ou B) Remplacer vos données originales par une version filtrée en utilisant ndimage.spline_filter
, puis appeler map_coordinates avec prefilter=False
.
même si vous avez assez de ram, garder l'ensemble de données filtrées autour peut être une grande accélération si vous avez besoin d'appeler map_coordinates plusieurs fois (par exemple, l'utilisation interactive, etc).
smooth spline interpolation in dim > 2 est difficile à mettre en œuvre, et donc il n'y a pas beaucoup de bibliothèques librement disponibles en mesure de le faire (en fait, je ne sais pas tout).
vous pouvez essayer l'interpolation pondérée inverse de distance, voir: L'Interpolation pondérée Inverse de Distance (IDW) avec Python . Cela devrait produire des résultats raisonnablement uniformes, et l'échelle mieux que RBF à de plus grands ensembles de données.