Транспонировать уплощенную матрицу из пар х, у - PullRequest
0 голосов
/ 08 декабря 2018

Мне дали одномерный массив десятичных чисел, которые представляют значения x и y.

Мне нужно транспонировать данный одномерный массив, как если бы это была матрица.

Myтекущий код делает это, но не полностью так, как мне хотелось бы:

to_transpose = [0.914, 0.639, 0.058, 0.760, 0.926, 0.475,
                0.255, 0.671, 0.195, 0.966, 0.336, 0.841,
                0.279, 0.341, 0.591, 0.638, 0.520, 0.225]
matrix_width = 6
matrix_height = 3
# INITIALIZE AN EMPTY LIST
transposed_list = [None] * matrix_width * matrix_height

for w in range(matrix_width):
    for h in range(matrix_height):
        transposed_list[w * matrix_height + h] = to_transpose[h * matrix_width + w]

Этот код правильно транспонирует матрицу, но не в том формате, который мне нужен.

Из-за того, что это массивиз значений x, y желаемый вывод показан ниже:

correct_output=[0.914, 0.639, 0.255, 0.671, 0.279, 0.341,
                0.058, 0.760, 0.195, 0.966, 0.591, 0.638,
                0.926, 0.475, 0.336, 0.841, 0.520, 0.225]

В правильном выводе каждые 2 десятичных знака рассматриваются как 1 при транспонировании.

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

Ответы [ 5 ]

0 голосов
/ 08 декабря 2018

Вы можете вычислить это без numpy и в одной строке / проходе, но это ужасно:

m=to_transpose # for easy writing only
[ n for l in zip( *[[(m[i],m[i+1]) for i in range(k,k+6,2)] for k in range(0,len(m),6)] ) for t in l for n in t ]

Вместо этого используйте numpy.

0 голосов
/ 08 декабря 2018

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

to_transpose = [0.914, 0.639, 0.058, 0.760, 0.926, 0.475,
                0.255, 0.671, 0.195, 0.966, 0.336, 0.841,
                0.279, 0.341, 0.591, 0.638, 0.520, 0.225]
matrix_width = 6
matrix_height = 3
# INITIALIZE AN EMPTY LIST
transposed_list = [None] * matrix_width * matrix_height

for w in range(0, matrix_width, 2):
    for h in range(matrix_height):
        transposed_list[w * matrix_height + (2 * h)] = to_transpose[h * matrix_width + w]
        transposed_list[(w * matrix_height + (2 * h)) + 1] = to_transpose[(h * matrix_width + w) + 1]
print(transposed_list)

Я сделал 3 вещи:

  • Сделано, чтобы пропустить нечетные значения, используя значение шага как 2
  • Добавлена ​​дополнительная строка, где нечетный элемент индекса получает значение y
  • Наконец, удваивается значение h, так что каждый чередуетсяэлемент получает новое значение
0 голосов
/ 08 декабря 2018

Если вы настаиваете на том, чтобы не использовать numpy для этого, я бы порекомендовал либо разделить значения x, y, либо сначала объединить их вместе:

to_transpose = [0.914, 0.639, 0.058, 0.760, 0.926, 0.475,
                0.255, 0.671, 0.195, 0.966, 0.336, 0.841,
                0.279, 0.341, 0.591, 0.638, 0.520, 0.225]
a = to_transpose

rows = 3
cols = 3
tot = rows*cols

# separated
x, y = a[::2], a[1::2]
xt = [x[i+j] for i in range(0, rows) for j in range(0, tot, cols)]
yt = [y[i+j] for i in range(0, rows) for j in range(0, tot, cols)]
transposed = [e for t in zip(xt, yt) for e in t]

# tupled
xy = [(i,j) for i,j in zip(a[::2], a[1::2])]
xyt = [xy[i+j] for i in range(0, rows) for j in range(0, tot, cols)]
transposed = [e for t in xyt for e in t]

Совершенно очевидно, что даже при этомработает, numpy будет гораздо лучшим инструментом для такого рода операций.

0 голосов
/ 08 декабря 2018
#!/bin/python3

to_transpose = [
    0.914, 0.639, 0.058, 0.760, 0.926, 0.475,
    0.255, 0.671, 0.195, 0.966, 0.336, 0.841,
    0.279, 0.341, 0.591, 0.638, 0.520, 0.225
]

matrix_width = 6
matrix_height = 3

to_transpose_with_pairs = [(to_transpose[2 * i], to_transpose[2 * i + 1]) for i in range(len(to_transpose) // 2)]
# [
#     (0.914, 0.639), (0.058, 0.76), (0.926, 0.475),
#     (0.255, 0.671), (0.195, 0.966), (0.336, 0.841),
#     (0.279, 0.341), (0.591, 0.638), (0.52, 0.225)
# ]

to_transpose_as_matrix = [None for _ in range(matrix_height)]

for row in range(matrix_height):
    start = row * matrix_width // 2
    end = start + matrix_width // 2

    to_transpose_as_matrix[row] = to_transpose_with_pairs[start:end]

# [
#     [(0.914, 0.639), (0.058, 0.76), (0.926, 0.475)],
#     [(0.255, 0.671), (0.195, 0.966), (0.336, 0.841)],
#     [(0.279, 0.341), (0.591, 0.638), (0.52, 0.225)]
# ]

transposed_as_matrix = list(map(list, zip(*to_transpose_as_matrix)))
# [
#     [(0.914, 0.639), (0.255, 0.671), (0.279, 0.341)],
#     [(0.058, 0.76), (0.195, 0.966), (0.591, 0.638)],
#     [(0.926, 0.475), (0.336, 0.841), (0.52, 0.225)]
# ]

transposed_with_pairs = [pair for row in transposed_as_matrix for pair in row]
# [
#     (0.914, 0.639), (0.255, 0.671), (0.279, 0.341),
#     (0.058, 0.76), (0.195, 0.966), (0.591, 0.638),
#     (0.926, 0.475), (0.336, 0.841), (0.52, 0.225)
# ]


transposed = [val for pair in transposed_with_pairs for val in pair]
# [
#     0.914, 0.639, 0.255, 0.671, 0.279, 0.341,
#     0.058, 0.76, 0.195, 0.966, 0.591, 0.638,
#     0.926, 0.475, 0.336, 0.841, 0.52, 0.225
# ]
0 голосов
/ 08 декабря 2018

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

>>> import numpy as np
>>> to_transpose = [0.914, 0.639, 0.058, 0.760, 0.926, 0.475,
                    0.255, 0.671, 0.195, 0.966, 0.336, 0.841,
                    0.279, 0.341, 0.591, 0.638, 0.520, 0.225]

>>> np.array(to_transpose).reshape((3,3,2)).transpose(1,0,2).ravel()
array([ 0.914,  0.639,  0.255,  0.671,  0.279,  0.341,
        0.058,  0.76 ,  0.195,  0.966,  0.591,  0.638,
        0.926,  0.475,  0.336,  0.841,  0.52 ,  0.225])

Разобьем это немного:

  • np.array превращает ваш список в array ...
  • , который вы затем reshape до 3x3x2,то есть матрица кортежей 3x3 ...
  • , которую вы затем transpose поменяете местами первую (0) и вторую (1) оси и сохраните третью (2) на месте ...
  • и, наконец, матрица снова сглаживается с помощью ravel

Если вы не можете использовать numpy в конце, вы все равно можете использовать это, чтобы правильно транспонировать матрицу индексов, чтобы выяснить, какой элементдолжен пойти куда-то, а затем воспроизвести это с помощью цикла над списком to_transpose:

>>> list(np.array(list(range(w*h))).reshape((3,3,2)).transpose(1,0,2).ravel())
[0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15, 4, 5, 10, 11, 16, 17]

>>> [i%2 + (i//2 * w % (w*h)) + 2 * (i//(h*2)) for i in range(w*h)]
[0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15, 4, 5, 10, 11, 16, 17]

>>> [to_transpose[i%2 + (i//2 * w % (w*h)) + 2 * (i//(h*2))] for i in range(w*h)]
[0.914, 0.639, 0.255, 0.671, 0.279, 0.341,
 0.058, 0.76, 0.195, 0.966, 0.591, 0.638,
 0.926, 0.475, 0.336, 0.841, 0.52, 0.225]

Конечно, вы можете сделать то же самое с обычными циклами вместо списочных представлений и на других языках.По сути, каждое из трех слагаемых в добавлении к индексу соответствует одному из измерений матрицы, и, честно говоря, я понял это больше, угадывая, чем реально понимая, что происходит.Само собой разумеется, что numpy решение намного чище.

...