#python #arrays #numpy
Вопрос:
У меня длинный массив, и я хочу применить его к пакету. Но, кроме того, я хочу ввести последние X
значения в новую партию.
Предположим, мне нужны пакеты из 10 значений, и я хочу повторить последние 2 значения.
import numpy as np
np.random.seed(9)
vals = np.random.randint(0, 9, 55)
Из: [5 6 8 6 1 6 4 8 1 8 5 1 0 8 8 8 2 6 8 1 8 3 5 3 6 7 0 8 1 8 1 6 6 2 8 4 5 3 4 0 8 0 4 5 4 8 3 8 4 8 0 1 2 3 7]
Тогда моя цель -:
[5 6 8 6 1 6 4 8 1 8]
[1 8 5 1 0 8 8 8 2 6]
[2 6 8 1 8 3 5 3 6 7]
[6 7 0 8 1 8 1 6 6 2]
[6 2 8 4 5 3 4 0 8 0]
[8 0 4 5 4 8 3 8 4 8]
[4 8 0 1 2 3 7]
Как вы можете видеть, последние два значения в одном массиве являются первыми двумя из следующего.
Я пытаюсь найти логику в этом, и я нашел следующую:
bs, ct = 10, 2 # ct = X in my question
print(vals[bs*0-0:bs*1-0])
print(vals[bs*1-2:bs*2-2])
print(vals[bs*2-4:bs*3-4])
print(vals[bs*3-6:bs*4-6])
print(vals[bs*4-8:bs*5-8])
print(vals[bs*5-10:bs*6-10])
print(vals[bs*6-12:bs*7-12])
Таким образом, я попытался создать цикл, но он не работает, и я уверен, что это должно быть проще.
print(vals[0 : bs])
for i in range(1, math.ceil(len(vals)/bs)):
print(vals[bs*i-2**i : bs*(i 1)-2**i])
Я попытался сделать следующее:
# Without repeating values works ok but not my goal
for i in range(0, len(vals), bs):
print(vals[i:i bs])
for i in range(0, len(vals), bs):
print(vals[i-ct:i bs])
Я пробую множество комбинаций, используя ct
и bt
, но всегда испытываю некоторые проблемы. Кто-нибудь может мне помочь, пожалуйста? Я знаю, что это должно быть проще, но я не могу найти логику…
Существует ли какой-то другой вариант более непосредственно, без использования для циклов? Может numpy
быть ? Я нашел np.split
и думаю np.reshape
, что, возможно, это сработает, но проблема в повторении значений X.
Спасибо!
Комментарии:
1.
[vals[i: i 10] for i in range(0, vals.size, 8)]
? Где8 == (bs - ct)
2. Можете ли вы написать это в качестве ответа? Я выберу его в качестве решения и закрою его
3. Конечно, через минуту.
4. @Cyttorak Вы уверены, что необходимо решение для составления списка? Разве для этого нет собственного решения numpy?
5. @Gulzar Есть, используя as_strided, но это немного опасно. И другие решения были бы дорогостоящими для памяти. Я постараюсь включить это в свой ответ.
Ответ №1:
Это можно сделать с помощью нарезки:
>>> bs, ct = 10, 2
>>> result = [vals[i: i bs] for i in range(0, vals.size, (bs - ct))]
>>> result
[array([5, 6, 8, 6, 1, 6, 4, 8, 1, 8]),
array([1, 8, 5, 1, 0, 8, 8, 8, 2, 6]),
array([2, 6, 8, 1, 8, 3, 5, 3, 6, 7]),
array([6, 7, 0, 8, 1, 8, 1, 6, 6, 2]),
array([6, 2, 8, 4, 5, 3, 4, 0, 8, 0]),
array([8, 0, 4, 5, 4, 8, 3, 8, 4, 8]),
array([4, 8, 0, 1, 2, 3, 7])]
Чего-то подобного можно также достичь с помощью numpy.lib.stride_tricks.as_strided
>>> from numpy.lib.stride_tricks import as_strided
>>> steps = vals.itemsize
>>> as_strided(
vals,
shape=(math.ceil(vals.size/(bs -ct)), 10),
strides=(steps*(bs - ct), steps)
)
array([[ 5, 6, 8, 6, 1, 6, 4, 8, 1, 8],
[ 1, 8, 5, 1, 0, 8, 8, 8, 2, 6],
[ 2, 6, 8, 1, 8, 3, 5, 3, 6, 7],
[ 6, 7, 0, 8, 1, 8, 1, 6, 6, 2],
[ 6, 2, 8, 4, 5, 3, 4, 0, 8, 0],
[ 8, 0, 4, 5, 4, 8, 3, 8, 4, 8],
[ 4, 8, 0, 1, 2, 3, 7, 121, 274, 34]])
Поскольку последние несколько значений не существуют, будут некоторые значения мусора. Тем не менее, as_strided
следует избегать, если вы не знаете, что делаете, и вам это абсолютно необходимо. Посмотрите документы.
Более безопасная альтернатива была введена в numpy.lib.stride_tricks.sliding_window_view
Комментарии:
1. Никогда раньше не читал этих заметок! Теперь мой внутренний хакер хочет выйти!