Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 填补numpy数组中的空白_Python_Numpy_Matplotlib_Scipy_Interpolation - Fatal编程技术网

Python 填补numpy数组中的空白

Python 填补numpy数组中的空白,python,numpy,matplotlib,scipy,interpolation,Python,Numpy,Matplotlib,Scipy,Interpolation,我只想用最简单的术语,插入一个3D数据集。线性插值,最近邻,所有这些就足够了(这是开始一些算法,所以不需要精确的估计) 在新的scipy版本中,griddata之类的东西会很有用,但目前我只有scipy 0.8。所以我有一个“立方体”(data[:,:,:],(NixNjxNk))数组,和一个大小相同的标志数组(flags[:,:,:,,],True或False)。我想使用数据中最近的有效数据点,或一些“相近”点的线性组合,为flag的对应元素为False的数据元素插入数据 数据集中至少在两个维

我只想用最简单的术语,插入一个3D数据集。线性插值,最近邻,所有这些就足够了(这是开始一些算法,所以不需要精确的估计)

在新的scipy版本中,griddata之类的东西会很有用,但目前我只有scipy 0.8。所以我有一个“立方体”(
data[:,:,:]
,(NixNjxNk))数组,和一个大小相同的标志数组(
flags[:,:,:,,]
True
False
)。我想使用数据中最近的有效数据点,或一些“相近”点的线性组合,为flag的对应元素为False的数据元素插入数据


数据集中至少在两个维度上可能存在较大的间隙。除了使用kdtrees或类似的方法编写一个完整的最近邻算法外,我真的找不到一个通用的、N维的最近邻插值器。

也许你要找的是一个机器学习算法,比如神经网络或支持向量机


您可以查看此页面,其中有一些指向python支持向量机包的链接:

您可以尝试解决您的问题,如:

# main ideas described in very high level pseudo code
choose suitable base kernel shape and type (gaussian?)
while true
    loop over your array (moving average manner)
        adapt your base kernel to current sparsity pattern
        set current value based on adapted kernel
    break if converged
这实际上可以以非常简单的方式实现(特别是在性能不是首要问题的情况下)

显然,这只是试探法,您需要用实际数据进行一些实验,以找到合适的适应方案。当将内核自适应视为内核重新加权时,您可能希望根据值的传播方式进行调整。例如,原始支撑的权重为1,它们与出现的迭代相关

此外,确定这一过程何时实际收敛可能是一个棘手的问题。根据应用情况,最终可能会合理地保留一些“空白区域”为“未填充”

更新:下面是一个非常简单的实现,大致如下*):

from numpy import any, asarray as asa, isnan, NaN, ones, seterr
from numpy.lib.stride_tricks import as_strided as ast
from scipy.stats import nanmean

def _a2t(a):
    """Array to tuple."""
    return tuple(a.tolist())

def _view(D, shape, strides):
    """View of flattened neighbourhood of D."""
    V= ast(D, shape= shape, strides= strides)
    return V.reshape(V.shape[:len(D.shape)]+ (-1,))

def filler(A, n_shape, n_iter= 49):
    """Fill in NaNs from mean calculated from neighbour."""
    # boundary conditions
    D= NaN* ones(_a2t(asa(A.shape)+ asa(n_shape)- 1), dtype= A.dtype)
    slc= tuple([slice(n/ 2, -(n/ 2)) for n in n_shape])
    D[slc]= A

    # neighbourhood
    shape= _a2t(asa(D.shape)- asa(n_shape)+ 1)+ n_shape
    strides= D.strides* 2

    # iterate until no NaNs, but not more than n iterations
    old= seterr(invalid= 'ignore')
    for k in xrange(n_iter):
        M= isnan(D[slc])
        if not any(M): break
        D[slc][M]= nanmean(_view(D, shape, strides), -1)[M]
    seterr(**old)
    A[:]= D[slc]
一个关于动作的
填充(.)
的简单演示如下:

In []: x= ones((3, 6, 99))
In []: x.sum(-1)
Out[]:
array([[ 99.,  99.,  99.,  99.,  99.,  99.],
       [ 99.,  99.,  99.,  99.,  99.,  99.],
       [ 99.,  99.,  99.,  99.,  99.,  99.]])
In []: x= NaN* x
In []: x[1, 2, 3]= 1
In []: x.sum(-1)
Out[]:
array([[ nan,  nan,  nan,  nan,  nan,  nan],
       [ nan,  nan,  nan,  nan,  nan,  nan],
       [ nan,  nan,  nan,  nan,  nan,  nan]])
In []: filler(x, (3, 3, 5))
In []: x.sum(-1)
Out[]:
array([[ 99.,  99.,  99.,  99.,  99.,  99.],
       [ 99.,  99.,  99.,  99.,  99.,  99.],
       [ 99.,  99.,  99.,  99.,  99.,  99.]])

*)所以这里的
nanmean(.)
只是用来演示适应过程的概念。基于此演示,实现更复杂的自适应和衰减称重方案应该非常简单。还要注意的是,没有注意实际的执行性能,但它仍然应该是好的(具有合理的输入形状)。

您可以设置一个晶体生长方式算法,沿每个轴交替移动视图,只替换标记为
False
但具有
True
邻居的数据。这给出了一个类似“最近邻”的结果(但不是欧几里德距离或曼哈顿距离——我认为如果你在计算像素,计算所有具有公共角点的连接像素,它可能是最近邻)。这对于NumPy应该相当有效,因为它只迭代轴和收敛迭代,而不是小数据片

原油,快速和稳定。我想这就是你想要的:

import numpy as np
# -- setup --
shape = (10,10,10)
dim = len(shape)
data = np.random.random(shape)
flag = np.zeros(shape, dtype=bool)
t_ct = int(data.size/5)
flag.flat[np.random.randint(0, flag.size, t_ct)] = True
# True flags the data
# -- end setup --

slcs = [slice(None)]*dim

while np.any(~flag): # as long as there are any False's in flag
    for i in range(dim): # do each axis
        # make slices to shift view one element along the axis
        slcs1 = slcs[:]
        slcs2 = slcs[:]
        slcs1[i] = slice(0, -1)
        slcs2[i] = slice(1, None)

        # replace from the right
        repmask = np.logical_and(~flag[slcs1], flag[slcs2])
        data[slcs1][repmask] = data[slcs2][repmask]
        flag[slcs1][repmask] = True

        # replace from the left
        repmask = np.logical_and(~flag[slcs2], flag[slcs1])
        data[slcs2][repmask] = data[slcs1][repmask]
        flag[slcs2][repmask] = True
为了更好地测量,这里是由最初标记为
True
的数据所播种的区域的可视化(2D)


使用scipy.ndimage,您的问题可以通过两行中的最近邻插值来解决:

from scipy import ndimage as nd

indices = nd.distance_transform_edt(invalid_cell_mask, return_distances=False, return_indices=True)
data = data[tuple(ind)]

现在,以函数的形式:

import numpy as np
from scipy import ndimage as nd

def fill(data, invalid=None):
    """
    Replace the value of invalid 'data' cells (indicated by 'invalid') 
    by the value of the nearest valid data cell

    Input:
        data:    numpy array of any dimension
        invalid: a binary array of same shape as 'data'. 
                 data value are replaced where invalid is True
                 If None (default), use: invalid  = np.isnan(data)

    Output: 
        Return a filled array. 
    """    
    if invalid is None: invalid = np.isnan(data)

    ind = nd.distance_transform_edt(invalid, 
                                    return_distances=False, 
                                    return_indices=True)
    return data[tuple(ind)]
使用示例:

def test_fill(s,d):
     # s is size of one dimension, d is the number of dimension
    data = np.arange(s**d).reshape((s,)*d)
    seed = np.zeros(data.shape,dtype=bool)
    seed.flat[np.random.randint(0,seed.size,int(data.size/20**d))] = True

    return fill(data,-seed), seed

import matplotlib.pyplot as plt
data,seed  = test_fill(500,2)
data[nd.binary_dilation(seed,iterations=2)] = 0   # draw (dilated) seeds in black
plt.imshow(np.mod(data,42))                       # show cluster
结果:

不久前,我为我的博士学位写了以下脚本:

例如:


慢一点,但能起作用。高斯核是最好的选择,只需检查大小/西格玛值。

这对于我的要求来说太过分了。我只需要用一个简单的“稳定”的插值机制来填补数据中的一些空白。这是一篇非常相关的文章:很好!一个(或两个)问题:如何推广这个解决方案来仲裁维度(1D,2D,…)不是很明显(至少对我来说)。但不管怎样,你似乎能够从内部攻击边界条件(相当不错),但是你是否意识到与这种方法相关的任何副作用?想进一步阐述这些问题吗?Thanks@eat:这是对ND的概括。只需将
形状更改为
(10,10,10,10,10)
,然后查看。我不明白你的第二个问题。你能用另一种方式重新表述它吗?是的,经过一段时间的修补,我会(有点)弄明白它是如何推广到ND的。不管怎么说,关于边界,我的意思是(用你的解决方案),你似乎根本不需要明确地说明它们(对吗?)。现在,由于我们似乎掌握了一些与OPs问题相关的实质性内容,比较一下它们在一些选定案例中的表现会好吗?也许在其他线程上,为了能够完全专注于主题。Thanks@eat:否,未明确定义填充值之间的边界。当然,我很乐意进一步讨论这个问题。我不知道有什么好的论坛可以合作。因此,这可能是一个很好的地方(只要你以问题的形式发布!)我在pastie.org上发布了代码,我想知道需要什么“调整”才能使其成为通用。我想已经是了。哇,我不知道距离变换edt。这是一个非常有用的函数。