合并NumPy数组并在Python中查找列

时间:2015-07-05 12:03:55

标签: python csv numpy pandas data-analysis

我是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 ]

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

我尝试使用numpy.concatenate,但它不适用于这两个矩阵。所以我在将matrix1matrix2转换为pandas DataFrames后尝试使用pandas merge函数。但是,这需要花费大量时间,所有矩阵都合并为一个单独的线性数组,如[1, 2, 3,4,5...],我没有办法区分matrix1matrix2mergedMatrix

所以我正在使用:

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

我的数据包含Inf等值。如果某列在Inf中包含值matrix1,我想删除该列以及相应的列,即matrix2中列号相同的列。

问题

  1. 有没有比使用列表mergedMatrix更好的方法?
  2. 如何快速查找matrix1列是否包含此类值而无需逐个检查每个元素及其列号?
  3. 实施例

    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文件中。

3 个答案:

答案 0 :(得分: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]

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

答案 1 :(得分:0)

我可以想到四个解决方案:

  • 使用您在问题中已经完成的列表。没有什么不妥。您可以按list[0][xx:yy]

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

  • 如果您真的想使用pandas,则必须在合并之前向数据添加标识符列(data1,data2),您可以使用groupy对数据进行分组或设置索引df.set_index('id_column')。但在我看来,这太过分了。

  • 如果您使用np.vstacknp.hstack(取决于它们相等的轴,您将丢失哪个矩阵所在的信息。除非您生成具有布尔ID的掩码例如

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

答案 2 :(得分:0)

假设您实际上并不需要mergedMatrix,请按以下步骤操作newMatrix1newMatrix2removedCols1和{{1}没有明确构建removedCols2

找到有趣的值

首先,让我们找一下mergedMatrix条目:

inf

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

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)

将其简化为列

您对单个元素不感兴趣,但哪些列具有任何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)

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

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

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

尼斯。这正是我们对>>> 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

NumPy否定了它的元素!这意味着我们可以>>> -matrix1_inf_columns array([ True, False, False], dtype=bool) 作为

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

嗷。 resize function?文档说当请求的大小大于数组时,它(除了我试图在这里使用的>>> 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 NumPy数组方法之外)不会在布尔数组的情况下填充零(resize )而是重复数组。

因此,让我们看看我们是否可以获得深层复制而不是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.]]) 中的无限值考虑到过滤,或者您的实际情况更复杂,那么会更复杂一些。但是你现在已经看到了你需要的大多数概念。