Перестановка строк в большом массиве с нулевым количеством нулей в некоторых строках. Как это исправить?

Я работаю с 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,)

Одна вещь, которую я предполагаю, я могу попытаться использовать разреженные матрицы, но мне просто интересно, смогу ли я заставить эту работу работать. У меня 256 ГБ оперативной памяти, поэтому я не думаю, что память является ограничением. Спасибо за ваши подсказки!

Ответ 1

Я сильно подозреваю вашу версию numpy. Я подозреваю, что это может быть проявлением этой ошибки, где вы можете увидеть, что установка большого массива на значение бесшумно выходит из строя и выводит нули. Возможно, можно отслеживать его для определенных версий с несколькими номерами и немного больше времени.

Здесь я написал тест script, который должен генерировать наборы данных, подобные тем, которые вы описываете (код, скопированный ниже для полноты). Я не могу воспроизвести исходную проблему.

Я могу настроить с помощью 59022 x 84122 np.array с dtype=np.uint16, но команда, представляющая интерес, выдает сообщение с памятью. Так что я am ограниченная память, поэтому не могу проверить точные значения, которые вы даете.

Однако, если я опускаю ширину до 54122, код работает как ожидалось (не выводит нули в строках > 7966).

Моя версия numpy

numpy.version.version == '1.8.2'

Моя версия и система python выглядит следующим образом:

Python 3.3.0 (v3.3.0: bd8afb90ebf2, 29.09.2012, 10:57:17) [MSC v.1600 64 бит (AM D64)] на win32


Код сценария

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 и применять функцию лямбда к новому столбцу, а затем сортировать ее в этом новом столбце:

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)