【问题标题】:rearranging rows in a big numpy array zeros some rows. How to fix it?重新排列大 numpy 数组中的行会使一些行归零。如何解决?
【发布时间】:2015-06-30 04:53:36
【问题描述】:

我正在使用 numpy 和以下数据(所有矩阵的所有单元格都不是负数):

>>> X1.shape
(59022, 16)
>>> X3.shape
(59022, 84122)
>>> ind.shape
(59022,)
>>> np.max( ind )
59021
>>> np.min( ind )
0
>>> len( set ( ind.tolist() ) )
59022

简而言之,ind 只是一种在任一矩阵中重新排列行的方法。问题是,虽然重新排列较小数组 (X1) 中的行可以按需要工作,但对较大数组 (X2) 的相同操作会导致某个点以下的所有行都为零。这是我的工作:

>>> np.nonzero( np.sum( X3, axis=1 ) )[0].shape
(59022,)

现在让我们看看如果重新排列行会发生什么:

>>> np.nonzero( np.sum( X3[ ind, : ], axis=1 ) )[0].shape
(7966,)

但对于较小的矩阵,一切正常:

>>> np.nonzero( np.sum( X1, axis=1 ) )[0].shape
(59022,)
>>> np.nonzero( np.sum( X1[ ind, : ], axis=1 ) )[0].shape
(59022,)

我猜我可以尝试的一件事是使用稀疏矩阵,但我只是想知道我是否可以让这件事发挥作用。我有 256GB 的 RAM,所以我不认为内存是一个限制。感谢您的提示!

【问题讨论】:

  • 你的数组是什么 dtypes (print X3.dtype)?您使用的是什么版本的 numpy (print np.__version__)? 84122 * 7966 略低于 2**30,对我来说,这听起来像是在 64 位系统中使用的 32 位指针/索引。您应该在 numpy github 问题中报告此问题,here
  • 我无法检查您的 X3 尺寸,但您是否尝试过使用 operator.itemgetterfrom operator import itemgetter; mygetter = itemgetter(*ind); np.allclose(mygetter(X1), X1[ ind, : ]) 为随机非负 X1 返回 True。也许 Numpy 和 itemgetter 都在底层使用相同的方法来重新排列数组,但也许不是,itemgetter 可能有效?
  • 可能修复是升级你的numpy版本,你用什么?

标签: python numpy


【解决方案1】:

我强烈怀疑你的 numpy 版本。我怀疑这可能是this bug 的一种表现形式,您可以看到将一个大数组设置为一个值会默默地失败并输出零。也许可以用 numpy 版本和更多时间来确定它。

我在这里编写了一个测试脚本,它应该会生成与您描述的数据集相似的数据集(为了完整起见,代码复制如下)。我无法重现原始问题..

我可以设置 59022 x 84122 np.arraydtype=np.uint16,但是感兴趣的命令会给出内存不足的消息。所以我内存有限,所以无法测试你给出的确切值。

但是,如果我将宽度降低到 54122,代码会按预期工作(不会在 > 7966 的行中输出零)。

我的 numpy 版本是

numpy.version.version == '1.8.2'

我的python版本和系统如下:

Win32 上的 Python 3.3.0(v3.3.0:bd8afb90ebf2,2012 年 9 月 29 日,10:57:17)[MSC v.1600 64 位 (AM D64)]


脚本代码

import numpy as np
import os

# Function to make some test data that will fit in memory...
def makeX(ind,width):
    rowcount = len(ind)
    Xret = np.ones((rowcount,width),dtype=np.uint16)
    col0 = ind.copy()
    col0 = col0.reshape((rowcount,1))
    np.random.shuffle(col0)

    for r in range(len(Xret)):
        Xret[r] = bytearray(os.urandom(width))
        Xret[r][0] = col0[r]

    return Xret

X3width = 54122 # if this is 84122, the last line fails with MemoryError on my box 
                # (16GB memory ~13 available)

ind = np.array(range(59022))
X1 = makeX(ind,16)
X3 = makeX(ind,54122)

print('Shapes of ind, X1 and X3')
print(ind.shape)
print(X1.shape)
print(X3.shape)

print('Contents of ind, X1 and X3')
print(ind)
print(X1)
print(X3)

print('Shape of np.nonzero( np.sum( X3, axis=1 ) )[0]')
print(np.nonzero( np.sum( X3, axis=1 ) )[0].shape)
print('Shape of np.nonzero( np.sum( X3, axis=1 ) )[0]')
print(np.nonzero( np.sum( X3[ ind, : ], axis=1 ) )[0].shape)

#This outputs (59022,) as expected

【讨论】:

    【解决方案2】:

    您是否尝试过将数据传递给 pandas 数据框结构并将 lambda 函数应用于新列,然后在此新列上对其进行排序:

    import pandas as pd
    
    df = pd.DataFrame(yournumpyarray)
    df.columns=['col1','col2',...,'coln']
    df['coln+1'] = df['col1'].apply(lambda x: myfunction(x)) + df['col2'].apply...
    df = df.sort('coln+1')
    df = df.drop('coln+1', 1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      • 2013-10-21
      相关资源
      最近更新 更多