Numpy: Как эффективно избавиться от минимумов по оси = 1, учитывая индексы?

Учитывая матрицу A формы (1000000,6), я понял, как получить минимальное крайнее правое значение для каждой строки, и реализовал это в этой функции:

def calculate_row_minima_indices(h): # h is the given matrix.
    """Returns the indices of the rightmost minimum per row for matrix h."""
    flipped = numpy.fliplr(h) # flip the matrix to get the rightmost minimum.
    flipped_indices = numpy.argmin(flipped, axis=1)
    indices = numpy.array([2]*dim) - flipped_indices
    return indices

indices = calculate_row_minima_indices(h)
for col, row in enumerate(indices):
    print col, row, h[col][row] # col_index, row_index and value of minimum which should be removed.

В каждой строке есть минимум. Итак, что мне нужно знать, так это удалить запись с минимумом и сжать матрицу с формой (1000000,6) до матрицы с формой (1000000,5) .

Я бы сгенерировал новую матрицу с меньшим размером и заполнил бы ее значениями, которые я хочу, чтобы она содержала, используя цикл for, но я боюсь времени выполнения. Итак, есть ли какой-то встроенный способ или какой-то трюк, чтобы уменьшить матрицу до минимума в строке?

Возможно, эта информация будет полезной: все значения больше или равны 0,0.


person Aufwind    schedule 20.02.2012    source источник


Ответы (2)


Предполагая, что у вас достаточно памяти для хранения логической маски формы вашего исходного массива, а также нового массива, вот один из способов сделать это:

import numpy as np

def main():
    np.random.seed(1) # For reproducibility
    data = generate_data((10, 6))

    indices = rightmost_min_col(data)
    new_data = pop_col(data, indices)

    print 'Original data...'
    print data
    print 'Modified data...'
    print new_data

def generate_data(shape):
    return np.random.randint(0, 10, shape)

def rightmost_min_col(data):
    nrows, ncols = data.shape[:2]
    min_indices = np.fliplr(data).argmin(axis=1)
    min_indices = (ncols - 1) - min_indices
    return min_indices

def pop_col(data, col_indices):
    nrows, ncols = data.shape[:2]
    col_indices = col_indices[:, np.newaxis]
    row_indices = np.arange(ncols)[np.newaxis, :]
    mask = col_indices != row_indices
    return data[mask].reshape((nrows, ncols-1))

if __name__ == '__main__':
    main()

Это дает:

Original data...
[[5 8 9 5 0 0]
 [1 7 6 9 2 4]
 [5 2 4 2 4 7]
 [7 9 1 7 0 6]
 [9 9 7 6 9 1]
 [0 1 8 8 3 9]
 [8 7 3 6 5 1]
 [9 3 4 8 1 4]
 [0 3 9 2 0 4]
 [9 2 7 7 9 8]]
Modified data...
[[5 8 9 5 0]
 [7 6 9 2 4]
 [5 2 4 4 7]
 [7 9 1 7 6]
 [9 9 7 6 9]
 [1 8 8 3 9]
 [8 7 3 6 5]
 [9 3 4 8 4]
 [0 3 9 2 4]
 [9 7 7 9 8]]

Один из менее читаемых трюков, которые я здесь использую, — использование трансляции numpy во время сравнения массивов. В качестве быстрого примера рассмотрим следующее:

import numpy as np
a = np.array([[1, 2, 3]])
b = np.array([[1],[2],[3]])
print a == b

Это дает:

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

Итак, если мы знаем индекс столбца элемента, который хотим удалить, мы можем векторизовать операцию для массива индексов столбцов, что и делает pop_col.

person Joe Kington    schedule 20.02.2012
comment
Вы можете сделать mask = np.ones(data.shape, 'bool'); mask[np.arange(nrows), col_indices] = False. Это может быть более читабельно. - person Bi Rico; 21.02.2012
comment
Однако это не то же самое. - person Joe Kington; 21.02.2012
comment
Кажется, это одно и то же, не могли бы вы объяснить, чем они отличаются? - person Bi Rico; 21.02.2012
comment
Ты прав, прошлой ночью я был немного туговат. Спасибо за предложение! - person Joe Kington; 21.02.2012

вы можете использовать массив логических масок, чтобы сделать выбор, но использование памяти немного велико.

import numpy

h = numpy.random.randint(0, 10, (20, 6))

flipped = numpy.fliplr(h) # flip the matrix to get the rightmost minimum.
flipped_indices = numpy.argmin(flipped, axis=1)
indices = 5 - flipped_indices

mask = numpy.ones(h.shape, numpy.bool)

mask[numpy.arange(h.shape[0]), indices] = False

result = h[mask].reshape(-1, 5)
person HYRY    schedule 20.02.2012