преобразование списка в матрицу с помощью numpy - PullRequest
0 голосов
/ 30 августа 2018

Начиная со списка поплавков, т.е.

register = [11, 12, 13, 23, 24, 34]

Я хотел бы создать симметричные матрицы, в которых элементы диагонали равны нулю, т.е.

[[  0.  11.  12.  13.]
 [ 11.   0.  23.  24.]
 [ 12.  23.   0.  34.]
 [ 13.  24.  34.   0.]]

Поэтому я решил создать ноль с размером 4 x 4, чтобы он был заполнен элементами моего списка. После установки индикатора прогресса и учета смещения, чтобы не перезаписывать нули диагонали, я затем либо переместился бы на восток (или юг), пока не будет использовано количество ранее определенных шагов для достижения предела матрицы. После увеличения прогресса и сброса счетчика начальных шагов, я мог бы перейти к следующему столбцу (строке), чтобы продолжить. Тем не менее, я допустил ошибку в своем нынешнем коде (по крайней мере, один раз - это мой первый контакт с numpy) и только собираю урожай

[[  0.  11.  12.  13.]
 [ 11.   0.  23.   0.]
 [ 12.  23.   0.   0.]
 [ 13.   0.   0.   0.]]

Мой код:

 import numpy as np
 dimension = 4    # other matrices' dimensions will be larger
 matrix = np.zeros((dimension,dimension))

 register = [11, 12, 13, 23, 24, 34]

 progress = 0
 inner_step = 0
 i = 0

 for progress in range(0, (dimension + 1)):
 permitted_steps = dimension - progress
 for i in range(progress, permitted_steps-1):
     matrix[(progress, inner_step+1+offset)] = register[0]
     matrix[(inner_step+1+offset, progress)] = register[0]
     inner_step += 1
     del register[0]

 progress += 1
 inner_step = 0
 offset += 1

Используемая целевая среда - Python 2.7 (Continuum Anaconda) для Windows.

Ответы [ 4 ]

0 голосов
/ 30 августа 2018

Вы были довольно близко, ваша проблема возникает, когда progress равен или больше permitted_steps-1, так как там нет диапазона для итерации. попробуйте это:

    import numpy as np

    dimension = 4
    matrix = np.zeros((dimension,dimension))

    register = [11, 12, 13, 23, 24, 34]
    progress = 0
    inner_step = 0
    i = 0
    offset = 0
    for progress in range(0, (dimension + 1)):
        permitted_steps = dimension - progress
        for i in range(0, permitted_steps-1):
            matrix[(progress, inner_step+1+offset)] = register[0]
            matrix[(inner_step+1+offset, progress)] = register[0]
            inner_step += 1
            del register[0]
        progress += 1
        inner_step = 0
        offset +=1
    print matrix

И это распечатает:

[[  0.  11.  12.  13.]
 [ 11.   0.  23.  24.]
 [ 12.  23.   0.  34.]
 [ 13.  24.  34.   0.]]

если вы измените массив регистров на длину 10:

register = [11, 12, 13, 23, 24, 34, 37, 39, 40, 43]

вы получите:

[[  0.  11.  12.  13.  23.]
 [ 11.   0.  24.  34.  37.]
 [ 12.  24.   0.  39.  40.]
 [ 13.  34.  39.   0.  43.]
 [ 23.  37.  40.  43.   0.]]
0 голосов
/ 30 августа 2018

Вот еще один векторизованный подход с triu_indices:

N = 4
idx = np.triu_indices(N, k=1)
matrix = np.zeros((N, N))
matrix[idx] = register
matrix.T[idx] = register

Создайте индексы для верхней треугольной матрицы со смещением по диагонали 1, а затем назначьте соответствующим образом.

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

assert len(register) == np.count_nonzero(1 - np.tri(N))
0 голосов
/ 30 августа 2018

Просто позвоните scipy.spatial.distance.squareform:

>>> import scipy.spatial.distance
>>> scipy.spatial.distance.squareform([11, 12, 13, 23, 24, 34])
array([[ 0, 11, 12, 13],
       [11,  0, 23, 24],
       [12, 23,  0, 34],
       [13, 24, 34,  0]])

Требуемое преобразование такое же, как преобразование из сжатой матрицы расстояний в матрицу расстояний квадратной формы, и scipy.spatial.distance.squareform выполняет это преобразование (и его обратное). Будьте осторожны с dtypes, хотя; [11, 12, 13, 23, 24, 34] - это список целых чисел, а не чисел с плавающей точкой, и передача его в squareform даст вам массив целых чисел. Вы можете преобразовать ввод в числа с плавающей точкой или вызвать result.astype(float), если хотите, числа с плавающей точкой.

0 голосов
/ 30 августа 2018

Вот один векторизованный подход, использующий broadcasting и masking/boolean-indexing -

r = np.arange(dimension)
mask = r[:,None] < r # Or in one step : ~np.tri(dimension,dtype=bool)
matrix[mask] = register
matrix.T[mask] = register

Если вам нужно вычислить dimension из заданного register, мы можем использовать:

dimension = int(np.ceil(np.sqrt(2*len(register))))

И для утверждения длины, учитывая dimension, мы могли бы иметь:

assert dimension*(dimension-1)//2 == len(register)

Кроме того, для производительности рассмотрите возможность подачи в массиве версии register.

Пробный прогон -

In [43]: import numpy as np
    ...: dimension = 4    # other matrices' dimensions will be larger
    ...: matrix = np.zeros((dimension,dimension))
    ...: 
    ...: register = [11, 12, 13, 23, 24, 34]

In [44]: r = np.arange(dimension)
    ...: mask = r[:,None] < r
    ...: matrix[mask] = register
    ...: matrix.T[mask] = register

In [45]: matrix
Out[45]: 
array([[ 0., 11., 12., 13.],
       [11.,  0., 23., 24.],
       [12., 23.,  0., 34.],
       [13., 24., 34.,  0.]])

Как masking может быть лучше, чем генерация всех треугольных индексов

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

In [3]: import numpy as np
   ...: dimension = 5000    # other matrices' dimensions will be larger
   ...: register = np.random.randint(0,10,dimension*(dimension-1)//2)

# With masking and boolean-indexing
In [4]: %%timeit
   ...: matrix = np.zeros((dimension,dimension),dtype=int)
   ...: r = np.arange(dimension)
   ...: mask = r[:,None] < r
   ...: matrix[mask] = register
   ...: matrix.T[mask] = register
10 loops, best of 3: 108 ms per loop

# With triangular indices indexing
In [5]: %%timeit
   ...: N = dimension
   ...: matrix = np.zeros((dimension,dimension),dtype=int)
   ...: idx = np.triu_indices(N, k=1)
   ...: matrix = np.zeros((N, N))
   ...: matrix[idx] = register
   ...: matrix.T[idx] = register
1 loop, best of 3: 364 ms per loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...