【问题标题】:Merging NumPy arrays and finding columns in Python合并 NumPy 数组并在 Python 中查找列
【发布时间】:2015-09-22 16:07:05
【问题描述】:

我是 Python 新手。我有两个 CSV 格式的数据文件。我将 CSV 文件数据加载到两个 NumPy 数组中:

matrix1 = numpy.genfromtxt(fileName1)
matrix2 = numpy.genfromtxt(fileName2)

两个矩阵的行和列不相等。

>>print(matrix1.shape)
(971, 4413)
>>print(matrix2.shape)
>>(5504, 4431)

我想以这样的方式组合matrix1和matrix2:

mergedMatrix = [ matrix1, matrix2 ]

我可以使用索引0matrix2 使用索引1mergedMatrix 访问matrix1

我尝试使用numpy.concatenate,但它不适用于这两个矩阵。所以我在将matrix1matrix2 转换为pandas DataFrames 后尝试使用pandas 合并功能。但是,这样做花费了很多时间,并且所有矩阵都被合并到一个单一的线性数组中,例如[1, 2, 3,4,5...],我无法区分mergedMatrix 中的matrix1matrix2

所以我正在使用:

#mergedMatrix as a list
mergedMatrix = [matrix1, matrix2]

我的数据包含像Inf 这样的值。如果一列在matrix1 中包含值Inf,我想删除该列以及相应的列,即matrix2 中具有相同列号的列。

问题

  1. 有没有比使用列表mergedMatrix 更好的方法?
  2. 如果不逐一检查每个元素及其列号,如何快速找到matrix1 列是否包含此类值?

示例:

matrix1 = [[1, 2, 3],
           [3, inf,0],
           [2 , inf, inf]]
matrix2 = [[0, 4, 2, 7],
           [0, 1, 0.5, 3],
           [1, 2, 3, 9]]

mergedMatrix = [[1, 2, 3],
           [3, inf,0],
           [2 , inf, inf],
           [0, 4, 2, 7],
           [0, 1, 0.5, 3],
           [1, 2, 3, 9]]

结果应该是:

mergedMatrix = [[1],
                [3],
                [2],
                [0,7],
                [0,3],
                [1,9]]

removedMatrixCols = [[2, 3],
               [inf,0],
               [inf, inf],
               [4, 2],
               [1, 0.5],
               [2, 3]]

那我要拆分矩阵:

newMatrix1 = [[1],
              [3],
              [2]]
newMatrix2 = [[0,7],
              [0,3],
              [1,9]]

removedCols1 = [[2, 3],
                [inf,0],
                [inf, inf]]

removedCols2 = [[4, 2],
                [1, 0.5],
                [2, 3]]

以便我可以将它们分别存储到 CSV 文件中。

【问题讨论】:

  • 添加一个包含一些虚拟数据的最小工作示例,包括您尝试过的步骤(例如使用 np.random.rand() )。您可以将数组存储在列表中,并通过list[0]list[0] 访问它们
  • 如果你能让两个矩阵大小相等,你可以使用numpy.dstack([matrix1, matrix2]),得到一个整洁的3D矩阵。
  • 使用 numpy 存储其数组的方式,您必须使两个矩阵的维度相等。
  • 你的矩阵的第二维真的是 4413 和 4431 吗?
  • @Moritz 补充说。是的,我知道我可以使用 list[0] 和 list[1] 访问矩阵。

标签: python csv numpy pandas data-analysis


【解决方案1】:

简而言之:技术上是,但不是真的,不是,是。

1:如果你想要一个 3-D 列表,你应该使用一个列表,但我也会把它变成一个数组 (mergedMatrix = numpy.array([matrix1, matrix2])),这样你仍然可以在新矩阵中使用逐个元素的逻辑

2:(注意:这些是完全不同的问题,因此,严格来说,应该在 2 个不同的问题中提出,而不是合并为一个,但我会活下来)

为此,您可以使用numpy.delete 删除列。要删除列,请使用axis=1 arg,例如:

new_mat = numpy.delete(mergedMatrix, cols_to_delete, axis=1)

mergedMatrix 和 cols_to_delete 都是数组。

您可以使用numpy.isinf,而不是使用嵌套的for 循环遍历数组以查找包含Inf 数字的列,然后您可以从上面替换cols_to_delete (*注意:cols_to_delete = numpy.isinf(merged_Matrix)[:,1]

无论如何,希望这会有所帮助! 干杯

【讨论】:

  • 问题中的这一行,“我可以使用索引 0 从合并矩阵访问 matrix1,使用索引 1 访问 matrix2”,让我认为 OP 想要一个 3D 矩阵。
  • 而且你不能 hstack/vstack 2 个具有不相等 2D 形状的数组(矩阵);至少有一个形状必须相等。
  • 重新阅读问题,我认为您是正确的..?至于不相等的形状,我将“4413”和“4431”误读为相同的......哎呀。更正了更新的第 1 部分
  • 4413 和 4431 可能是一个错字,因为 OP 询问是否根据矩阵 1 中的值标记矩阵 2 中的列。在这种情况下,这将是一个示例,为什么总是需要复制-粘贴东西。
  • 很可能。如果不是这样,matrix2 的第 4425 列很可能会有一个无法从 matrix1 中删除的inf 元素,所以@OP,如果这不是错别字,请注意这一点
【解决方案2】:

我能想到四种解决方案:

  • 按照您在问题中所做的那样使用列表。没有什么不妥。您可以通过list[0][xx:yy]

  • 索引您的数组
  • 将数据存储在字典中,例如 {1:matrix1,2:matrix2}

  • 1234563 @。但在我看来,这太过分了。
  • 如果您使用 np.vstacknp.hstack(取决于它们相等的轴,您将丢失哪个矩阵是哪个矩阵的信息。除非您生成一个带有布尔 id 的掩码,例如

    mask = np.ones(len(merged_matrix)) mask[0:len(matrix1)] = 0

【讨论】:

    【解决方案3】:

    假设您实际上不需要mergedMatrix,以下是您可以在不显式构造mergedMatrix 的情况下获得newMatrix1newMatrix2removedCols1removedCols2 的方法。

    找到有趣的值

    首先,我们去找inf 条目:

    import numpy as np
    matrix1 = np.genfromtxt(fileName1)
    matrix2 = np.genfromtxt(fileName2)
    
    matrix1_infs = matrix1 == float('inf')
    
    # or if you want to treat -inf the same as inf:
    matrix1_infs = np.isinf(matrix1)
    

    这为您提供了一个布尔型 2D NumPy 数组。对于您的小示例数组,它将是

    array([[False, False, False],
           [False,  True, False],
           [False,  True,  True]], dtype=bool)
    

    将其归结为列

    您对单个元素不感兴趣,而是对哪些列具有任何 inf 值感兴趣。一个直接的找出方法是使用

    matrix1_inf_columns = matrix1_infs.any(axis=0)
    

    更难理解的是使用线性代数和布尔代数的组合来得出以下向量矩阵乘积:

    matrix1_inf_columns = np.dot(np.repeat(True, matrix1.shape[1]), matrix1_infs)
    

    结果是一样的:

    array([False,  True,  True], dtype=bool)
    

    使用布尔索引数组进行切片

    对于其他 NumPy 数组,when you use boolean NumPy arrays as indices 发生了一些有趣的事情:

    >>> matrix1[:, matrix1_inf_columns] # First index is rows, second columns.
                                        # : means all. Thus here:
                                        # All rows, but only the selected columns.
    array([[  2.,   3.],
           [ inf,   0.],
           [ inf,  inf]])
    

    很好。这正是我们想要的removedCols1。但它变得更加疯狂。当你取一个布尔数组的负数时会发生什么?

    >>> -matrix1_inf_columns
    array([ True, False, False], dtype=bool)
    

    NumPy 否定它的元素!这意味着我们可以得到newMatrix1

    newMatrix1 = matrix1[:, -matrix1_inf_columns]
    # array([[ 0.],
    #        [ 0.],
    #        [ 1.]])
    

    当然,布尔索引数组并不知道它最初是从matrix1 构造的,所以我们可以很容易地使用它来索引matrix2

    removedCols2 = matrix2[:, matrix1_inf_columns]
    # array([[ 4. ,  2. ],
    #        [ 1. ,  0.5],
    #        [ 2. ,  3. ]])
    

    但如果布尔索引数组比索引数组的维度短,它将假定False 缺少布尔索引:

    >>> matrix2[:, -matrix1_inf_columns]
    array([[ 0.],
           [ 0.],
           [ 1.]])
    

    这不是我们想要的完整的newMatrix2

    尺寸问题

    所以我们必须使用更大的索引数组。

    >>> matrix1_inf_columns.resize(matrix2.shape[1])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: cannot resize an array references or is referenced
    by another array in this way.  Use the resize function
    

    哦。 resize function?文档说,当请求的大小大于数组时,它将(除了我在这里尝试使用的resize NumPy 数组方法)不填充零(False 在布尔数组的情况下)而是重复数组。

    那么让我们看看我们是否可以在matrix1 上获得深层副本而不是视图:

    >>> tmp = matrix1_inf_columns.copy()
    >>> tmp.resize(matrix2.shape[1])
    >>> tmp
    array([False,  True,  True, False], dtype=bool)
    >>> -tmp
    array([ True, False, False,  True], dtype=bool)
    

    好的,成功了。让我们将它作为matrix2 的索引插入。

    removedCols2 = matrix2[:, tmp]
    # array([[ 4. ,  2. ],
    #        [ 1. ,  0.5],
    #        [ 2. ,  3. ]])
    

    太好了,所以这仍然有效。

    newMatrix2 = matrix2[:, -tmp]
    # array([[ 0.,  7.],
    #        [ 0.,  3.],
    #        [ 1.,  9.]])
    

    耶!

    到无穷大... 及以后

    如果您还想将matrix2 中的无限值考虑在内进行过滤,或者您的实际情况更加复杂,这将变得更加复杂。但是您现在已经看到了您需要的大部分概念。

    【讨论】:

      猜你喜欢
      • 2017-12-23
      • 1970-01-01
      • 2021-09-05
      • 1970-01-01
      • 2015-11-02
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      • 2013-07-06
      相关资源
      最近更新 更多