【问题标题】:python/numpy combine subarrays 4 rows at a timepython/numpy一次组合4行子数组
【发布时间】:2018-11-14 02:20:54
【问题描述】:

我有一个由每一行分割的 numpy 数组:

splitArray:


[[0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0]]

我希望每 4 行合并一次所述 splitArray,最后一个子数组不一定必须是 4,而只是剩下的部分。

下面是我希望拥有的数组:

joinedArray:


[[0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0],
 [0,   0,   0,   0,   0,   0,  0,
  0,   0,   0,   0,   0,   0,  0]]

【问题讨论】:

  • 除非你想转换回list而不是np.array,否则你不能有不等长的行。
  • numpy 不适用于锯齿状数组

标签: python list numpy split


【解决方案1】:

使用列表组合:

[a[i:i+4] for i in range(0, len(a), 4)]
#[array([[0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0]]),
# array([[0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0]]),
# array([[0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0]]),
# array([[0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0]])]

【讨论】:

  • 如果您使用切片,则结尾 [start:end] 可能会安全地超过对象的长度,在这种情况下,它会简单地转换为 -1。您可以安全地省略 min() 语句,只需 a[i:i+4]
  • @Aaron Cool,我想我真的是新人,只是不太记得了-可能是因为向后遍历它们或其他什么!
【解决方案2】:

作为一种纯粹的 Numpythonic 方法,您可以通过创建从分块数到行数的范围,将分块数设置为 rangestep arg,从而找到拆分数组所需的所有索引。然后使用np.split() 分割你的数组:

In [24]: def chunk_array(arr, ch):
    ...:     x = arr.shape[0]
    ...:     return np.split(a, np.arange(ch, x, ch))
    ...: 
    ...: 

演示:

In [25]: chunk_array(a, 4)
Out[25]: 
[array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]])]

In [26]: chunk_array(a, 3)
Out[26]: 
[array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]]), array([[0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0]])]

如果您希望连接分块数组,您可以使用@jpp 的答案与np.concatenate()map 或在列表理解中略有不同。

In [75]: def chunk_array(arr, ch):
    ...:     x = arr.shape[0]
    ...:     return [np.concatenate(subs) for subs in np.split(arr, np.arange(ch, x, ch))]

【讨论】:

  • 这实际上并没有像列表理解那样将工作推到 C 中; numpy.split 在 Python 级别迭代并以与列表推导相同的方式对数组进行切片,但需要额外的开销。
  • @user2357112 是的,但是np.split 是功能性的,Numpythonic 并且可以与其他 Numpy 函数一起调整。为了防止未来的用户走错方向,另一个重要的一点是术语“列表理解迭代在 C 中执行”或“将工作推到 C”(正如许多书籍、SO 答案、博客文章中提到的那样)等)是关于 Python 的最普遍、完全错误的神话之一。列表推导更快是因为暂停和恢复函数的帧很慢,而不是因为列表推导有什么特别之处。
  • 我从这个开始(事实上,我的 np.split 实现是相同的),但是 OP 想要的输出是别的东西。是否应该修改问题或澄清我们的目标?
  • @jpp 你完全正确。我没有注意到,即使是列表理解的其他答案也没有连接子数组。让我更新答案。我仍然不知道为什么您的回答不被接受 :)) 但感谢您提及这一点。
【解决方案3】:

这可以使用臭名昭著的grouper 配方来完成。

>>> from itertools import zip_longest
>>> import numpy as np
>>> 
>>> data = [7 * [0] for i in range(14)]
>>> i=iter(data); list(map(np.concatenate, zip_longest(*4*(i,), fillvalue=[])))
[array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0]), array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])]

【讨论】:

    【解决方案4】:

    您可以将np.concatenatenp.split 一起使用。如果需要,您可以调整以下示例以输出列表列表而不是数组列表。

    如前所述,单个锯齿状 numpy 数组不是一个好主意。

    A = np.zeros((14, 3))
    
    res = list(map(np.concatenate, np.split(A, np.arange(4, A.shape[0], 4))))
    
    print(res)
    
    [array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),
     array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),
     array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]),
     array([ 0.,  0.,  0.,  0.,  0.,  0.])]
    

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 2020-10-06
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-06
      相关资源
      最近更新 更多