【问题标题】:Numpy concatenate lists where first column is in range nNumpy 连接列表,其中第一列在范围 n 中
【发布时间】:2020-02-02 16:49:29
【问题描述】:

我正在尝试选择名为matrix 形状为(25323, 9) 的numpy 矩阵中的所有行,其中列表@ 中每个元组的第一列的值在startend 的范围内987654325@。最终,我想创建一个新的 numpy 矩阵,其结果是final 的形状为(n, 9)。以下代码返回此错误:TypeError: only integer scalar arrays can be converted to a scalar index。我也尝试使用numpy.zeros((1,9)) 初始化final 并使用np.concatenate,但得到了类似的结果。当我使用final.append(result) 而不是使用np.concatenate 时,我确实得到了编译结果,但是矩阵的形状会丢失。我知道这个问题有适当的解决方案,任何帮助将不胜感激。

  final = []
  for i in range_tuples:
    copy = np.copy(matrix)
    start = i[0]
    end = i[1]
    result = copy[(matrix[:,0] < end) & (matrix[:,0] > start)]
    final = np.concatenate(final, result)

  final = np.matrix(final)

【问题讨论】:

  • concatenate 获取数组列表和轴号。你试着给它两个数组。它反对将第二个数组用作数字。哦,不要像这样使用concatenate。初始化很慢而且很难。使用列表追加。
  • 要明确一点,每个result 将是(n1, 9) 形状,n1 可以在哪里不同?您希望结果是一个 (n,9),其中n 是所有n1 的总和?你试过vstack加入数组列表吗?

标签: python numpy vectorization


【解决方案1】:
In [33]: arr                                                                                   
Out[33]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17],
       [18, 19, 20],
       [21, 22, 23]])
In [34]: tups = [(0,6),(3,12),(9,10),(15,14)]                                                  
In [35]: alist=[] 
    ...: for start, stop in tups: 
    ...:     res = arr[(arr[:,0]<stop)&(arr[:,0]>=start), :] 
    ...:     alist.append(res) 
    ...:                                                                                       

检查列表;注意元素的形状不同;有些是 1 或 0 行。测试这些边缘情况是个好主意。

In [37]: alist                                                                                 
Out[37]: 
[array([[0, 1, 2],
        [3, 4, 5]]), array([[ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11]]), array([[ 9, 10, 11]]), array([], shape=(0, 3), dtype=int64)]

vstack 加入他们:

In [38]: np.vstack(alist)                                                                      
Out[38]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [ 9, 10, 11]])

这里concatenate 也可以,因为默认轴是0,并且所有输入都已经是2d了。

【讨论】:

  • 完美。谢谢!
【解决方案2】:

试试下面的

final = np.empty((0,9))
for start, stop in range_tuples:
    result = matrix[(matrix[:,0] < end) & (matrix[:,0] > start)]
    final = np.concatenate((final, result))

首先是将final初始化为一个numpy数组。 concatenate 的第一个参数必须是数组的 python 列表,请参阅docs。在您的代码中,它将result 变量解释为参数axis 的值

注意事项

  • 我使用元组解构使循环更清晰
  • 不需要副本
  • 附加列表可以更快。之后可以通过reshaping获得最终结果,前提是result的长度始终相同。

【讨论】:

    【解决方案3】:

    我会简单地创建一个布尔掩码来选择满足所需条件的行。

    编辑:我错过了您正在使用matrix(与ndarray 相反)。已为 matrix 编辑答案。

    假设以下输入数据:

    matrix = np.matrix([[1, 2, 3], [5, 6, 7], [2, 1, 7], [3, 4, 5], [8, 9, 0]])
    range_tuple = [(0, 2), (1, 4), (1, 9), (5, 9), (0, 100)]
    

    然后,首先,我会将range_tuple 转换为numpy.ndarray

    range_mat = np.matrix(range_tuple)
    

    现在,创建面具:

    mask = np.ravel((matrix[:, 0] > range_mat[:, 0]) & (matrix[:, 0] < range_mat[:, 1]))
    

    应用遮罩:

    final = matrix[mask]  # or matrix[mask].copy() if you intend to modify matrix
    

    检查:

    print(final)
    [[1 2 3]
     [2 1 7]
     [8 9 0]]
    

    如果range_tuple 的长度可能与matrix 中的行数不同,则执行以下操作:

    n = min(range_mat.shape[0], matrix.shape[0])
    mask = np.pad(
        np.ravel(
            (matrix[:n, 0] > range_mat[:n, 0]) & (matrix[:n, 0] < range_mat[:n, 1])
        ),
        (0, matrix.shape[0] - n)
    )
    final = matrix[mask]
    

    【讨论】:

      猜你喜欢
      • 2017-01-30
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-29
      • 1970-01-01
      相关资源
      最近更新 更多