Повторите значения в столбце на основе другого - PullRequest
0 голосов
/ 01 февраля 2019

Предположим, у меня есть массив (не обязательно квадратный)

my_array = ['name_1', 3
            'name_2', 2]

, и я хочу в итоге получить список (или простой массив и т. Д.) length 3+2=5, где первые три позиции назначены 'name_1' и следующие 2 до 'name_2'.Следовательно, результат будет

['name_1', 'name_1', 'name_1', 'name_2', 'name_2']

Это то, что я сделал до сих пор;Есть ли лучший способ сделать это, пожалуйста?

import numpy as np

my_array = np.array([['name_1', 3], ['name_2', 2]])
l = []
for i in range(my_array.shape[0]):
    x = [my_array[i, 0].tolist()] * np.int(my_array[i, 1])
    l.append(x)

flat_list = [item for sublist in l for item in sublist]
print(flat_list)

, который печатает:

['name_1', 'name_1', 'name_1', 'name_2', 'name_2']

Спасибо!

Ответы [ 5 ]

0 голосов
/ 01 февраля 2019

Использование списка понимания:

In [3]: my_array = ['name_1', 3, 'name_2', 2]
In [4]: out = [i for i, j in zip(my_array[::2], my_array[1::2]) for _ in range(j)]
In [5]: out
Out[5]: ['name_1', 'name_1', 'name_1', 'name_2', 'name_2']
0 голосов
/ 01 февраля 2019

Вот еще один подход, пропускающий itertools, предпочитающий генераторы:

def expanded(matrix):
    stream = iter(matrix)
    for element, count in zip(stream, stream):
        for _ in range(count):
            yield element

list(expanded(my_array))
0 голосов
/ 01 февраля 2019

Использование np.repeat:

my_array[:,0].repeat(my_array[:,1].astype(int))
# array(['name_1', 'name_1', 'name_1', 'name_2', 'name_2'], dtype='<U6')
0 голосов
/ 01 февраля 2019

Я не тупой эксперт, и "лучший" способ субъективен.Вот один из способов использования itertools

from itertools import chain, repeat
chain.from_iterable(repeat(elem, count) for elem, count in zip(my_array[::2], my_array[1::2]))

Вот подробное описание того, как это работает.

my_array[::2] возвращает фрагмент, который является любым другим элементом, поскольку первый и второй аргументыоставлено пустым, начинается с 0 и продолжается до конца.Так что это будет весь ваш первый столбец, который является вашими элементами ввода.Ваши значения находятся в другом столбце, поэтому мы можем использовать my_array[1::2] для получения значений.Эти фрагменты хороши тем, что они не создают новые копии вашего массива, а просто «представления», которые пропускают каждый второй элемент и начинаются с некоторого смещения.

Теперь мы хотим перечислить их попарно.Использование zip() удобно для этого.Он использует итераторы / генераторы / последовательности параллельно и дает индивидуальную привязку для каждого элемента.Поэтому, когда мы проникаем в конструкцию for, мы привязываем каждый элемент к elem, а каждый счет к count.

Конструкция for in позволяет нам обеспечить преобразование для каждой пары аргументов.Здесь мы используем repeat для создания виртуальных повторений каждого элемента.Снова хорошо, что нам не нужно создавать новые массивы.Генератор repeat просто сгенерирует входной элемент N раз.

Наконец, нам нужен способ объединить все эти повторяющиеся элементы в одно сведенное перечисление.Вот тут и приходит chain.from_iterable(). Он потребляет многократные итерируемые элементы, развертываемые последовательно.Как и другие части, цепочка создаст новый генератор, а не новый список, поэтому мы снова сэкономим память.Если вы действительно хотите список, вы можете добавить его к list() в конце.Или просто сделайте его входом для конструкции for in.

Вот все, что разбито на отдельные операции с намерением-раскрывающими-переменными:

elements = my_array[::2]
counts = my_array[1::2]
bypairs = zip(elements, counts)
repeated = (repeat(elem, count) for elem, count in bypairs)
flattened = chain.from_iterable(repeated)
list(flattened)
0 голосов
/ 01 февраля 2019

Вы можете использовать комбинацию умножения списка и sum:

sum(([my_array[i]] * my_array[i+1] for i in range(0, len(my_array), 2)), [])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...