“撤消” numpy.delete,numpy.insert?

时间:2019-10-28 21:49:07

标签: python arrays numpy

我有numpy数组,我想删除少量条目。之后,我想将先前的索引插入它们所属的位置。 numpy.insert不能解决问题:

import numpy

a = numpy.random.rand(7)
idx = [5, 0]

# delete some indices
b = numpy.delete(a, idx)

# magic
b /= 1.0

# insert back?
c = numpy.insert(b, idx, a[idx])

# nope :(
assert numpy.all(numpy.abs(a - c) < 1.0e-10)

有任何提示吗? (首选简单答案。)

也许有比首先使用delete更好的解决方案,例如通过切片等。

3 个答案:

答案 0 :(得分:1)

这是array-assignment的一种方式-

out = np.empty(len(b) + len(idx), dtype=b.dtype)
out[idx] = vals
out[np.isin(np.arange(len(out)), idx, invert=True)] = b

另一种方法涉及一些排序-

sidx = idx.argsort()
out = np.insert(b, idx[sidx] - np.arange(len(idx)), vals[sidx])

请注意,解决方案假定输入为数组。

答案 1 :(得分:1)

我认为您想做的只是用整数索引屏蔽:

import numpy as np

a = np.random.rand(7)
c = a.copy()
idx = 5, 0

# get the complement of idx
not_idx = np.fromiter((i for i in range(a.size) if i not in idx), dtype=int)
# ...or (mind the final comma: you need a `tuple` of `tuple`s):
not_idx = tuple(i for i in range(a.size) if i not in idx),

# magic
a[not_idx] /= 1.0

# yes!
assert np.all(np.abs(a - c) < 1.0e-10)
# perhaps you would prefer: `np.all(np.isclose(a, c))`?

一种更有效的方法可能是对所有内容进行“魔术”处理,然后将您想要的未修改内容复制回结果中,例如:

import numpy as np

a = np.random.rand(7)
c = a.copy()
idx = 5, 0

# magic
a /= 1.0

# copy stuff back
a[idx,] = c[idx,]

# yes!
assert np.all(np.abs(a - c) < 1.0e-10)

答案 2 :(得分:1)

这是一种方法,它首先重新排列未删除的位,然后填充已删除的位。诚然,与@Divakar的第一种方法并不太相似,但据我所知,它可以更快一点:

enter image description here

代码:

import numpy as np
from simple_benchmark import BenchmarkBuilder, MultiArgument

B = BenchmarkBuilder()

@B.add_function()
def pp(b,idx,aidx):
    N,n = b.size,idx.size
    B = np.empty(N+n,b.dtype)
    m = np.ones(N+n,bool)
    m[idx] = False
    B[m] = b
    B[idx] = aidx
    return B

@B.add_function()
def div1(b,idx,vals):
    out = np.empty(len(b)+len(idx),dtype=b.dtype)
    out[idx] = vals
    out[np.isin(np.arange(len(out)),idx, invert=True)] = b
    return out

@B.add_function()
def div2(b,idx,vals):
    sidx = idx.argsort()
    return np.insert(b, idx[sidx]-np.arange(len(idx)), vals[sidx])

@B.add_arguments('array size')
def argument_provider():
    for exp in range(1,13):
        sz = int(2**exp)
        a = np.random.randint(0,100,sz*sz)
        idx = np.random.choice(sz*sz,sz,replace=False)
        b = np.delete(a,idx)
        yield sz*sz,MultiArgument([b,idx,a[idx]])

r = B.run()
r.plot(relative_to=pp)

import pylab
import pathlib
pylab.savefig(pathlib.Path(__file__).stem + '.png')