【问题标题】:How can I pad and/or truncate a vector to a specified length using numpy?如何使用 numpy 将向量填充和/或截断到指定长度?
【发布时间】:2015-11-13 10:02:20
【问题描述】:

我有几个列表:

a = [1,2,3]
b = [1,2,3,4,5,6]

长度可变。

我想返回一个长度为 5 的向量,这样如果输入列表长度 5 则在第 5 个元素处截断.

例如,输入a 将返回np.array([1,2,3,0,0]),输入b 将返回np.array([1,2,3,4,5])。

我觉得我应该可以使用np.pad,但我似乎无法按照文档进行操作。

【问题讨论】:

  • 使用 np.pad, np.pad(x,((0,5-len(x))),mode='constant', constant_values=0) 是array([1, 2 , 3, 0, 0]) 对于 x = np.array([1,2,3]),但是它不适用于 len(x) > 5 所以在这种情况下只需对数组进行切片,例如如果 y = np.array([1,2,3,4,5,6]) 然后 y[:5] = array([1, 2, 3, 4, 5])

标签: python numpy


【解决方案1】:

这可能是慢是快,我不确定,但它适用于您的目的。

In [22]: pad = lambda a,i : a[0:i] if len(a) > i else a + [0] * (i-len(a))

In [23]: pad([1,2,3], 5)
Out[23]: [1, 2, 3, 0, 0]

In [24]: pad([1,2,3,4,5,6,7], 5)
Out[24]: [1, 2, 3, 4, 5]

【讨论】:

  • 对于 numpy 版本:pad = lambda a, i: a[0: i] if a.shape[0] > i else np.hstack((a, np.zeros(i - a.shape[0])))
【解决方案2】:

np.pad 太过分了,在 2d 图像周围添加边框比在列表中添加一些零更好。

我喜欢zip_longest,特别是如果输入是列表,并且不需要是数组。它可能是最接近在编译代码中一次对所有列表进行操作的代码的代码)。

a, b = zip(*list(itertools.izip_longest(a, b, fillvalue=0)))

是一个完全不使用np.array的版本(节省了一些数组开销)

但它本身不会截断。它仍然像[x[:5] for x in (a,b)]。

这是我对all_ms 函数的变体,使用简单的列表或一维数组:

def foo_1d(x, n=5):
    x = np.asarray(x)
    assert x.ndim==1
    s = np.min([x.shape[0], n])
    ret = np.zeros((n,), dtype=x.dtype)
    ret[:s] = x[:s]
    return ret

In [772]: [foo_1d(x) for x in [[1,2,3], [1,2,3,4,5], np.arange(10)[::-1]]]
Out[772]: [array([1, 2, 3, 0, 0]), array([1, 2, 3, 4, 5]), array([9, 8, 7, 6, 5])]

numpy 解决方案的一种或其他方式做同样的事情 - 构造一个所需形状的空白数组,然后用原始的相关值填充它。

另一个细节 - 理论上,截断解决方案时可以返回视图而不是副本。但这需要与垫盒分开处理。


如果所需的输出是等长数组的列表,则可能值得将它们收集到二维数组中。

In [792]: def foo1(x, out):
    x = np.asarray(x)
    s = np.min((x.shape[0], out.shape[0]))
    out[:s] = x[:s]

In [794]: lists = [[1,2,3], [1,2,3,4,5], np.arange(10)[::-1], []]

In [795]: ret=np.zeros((len(lists),5),int)
In [796]: for i,xx in enumerate(lists):
    foo1(xx, ret[i,:])
In [797]: ret
Out[797]: 
array([[1, 2, 3, 0, 0],
       [1, 2, 3, 4, 5],
       [9, 8, 7, 6, 5],
       [0, 0, 0, 0, 0]])

【讨论】:

    【解决方案3】:

    纯python版本,其中a是一个python列表(不是numpy数组):a[:n] + [0,]*(n-len(a))。

    例如:

    In [42]: n = 5
    
    In [43]: a = [1, 2, 3]
    
    In [44]: a[:n] + [0,]*(n - len(a))
    Out[44]: [1, 2, 3, 0, 0]
    
    In [45]: a = [1, 2, 3, 4]
    
    In [46]: a[:n] + [0,]*(n - len(a))
    Out[46]: [1, 2, 3, 4, 0]
    
    In [47]: a = [1, 2, 3, 4, 5]
    
    In [48]: a[:n] + [0,]*(n - len(a))
    Out[48]: [1, 2, 3, 4, 5]
    
    In [49]: a = [1, 2, 3, 4, 5, 6]
    
    In [50]: a[:n] + [0,]*(n - len(a))
    Out[50]: [1, 2, 3, 4, 5]
    

    使用 numpy 的函数:

    In [121]: def tosize(a, n):
       .....:     a = np.asarray(a)
       .....:     x = np.zeros(n, dtype=a.dtype)
       .....:     m = min(n, len(a))
       .....:     x[:m] = a[:m]
       .....:     return x
       .....: 
    
    In [122]: tosize([1, 2, 3], 5)
    Out[122]: array([1, 2, 3, 0, 0])
    
    In [123]: tosize([1, 2, 3, 4], 5)
    Out[123]: array([1, 2, 3, 4, 0])
    
    In [124]: tosize([1, 2, 3, 4, 5], 5)
    Out[124]: array([1, 2, 3, 4, 5])
    
    In [125]: tosize([1, 2, 3, 4, 5, 6], 5)
    Out[125]: array([1, 2, 3, 4, 5])
    

    【讨论】:

      猜你喜欢
      • 2017-08-23
      • 2023-03-15
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      相关资源
      最近更新 更多