Разрезать массив на сегменты - PullRequest
2 голосов
/ 18 января 2020

Предположим, у меня есть массив [1,2,3,4,5,6,7,8] ,, и массив состоит из двух выборок [1,2,3,4] и [5,6,7,8]. Для каждого образца я хочу сделать окно среза с размером окна n. И если не хватает элементов, дополните результат последними элементами. Каждая строка в возвращаемом значении должна быть нарезанным окном, начиная с элемента в этой строке.

Например: если n=3, то результат должен быть:

[[1,2,3],
 [2,3,4],
 [3,4,4],
 [4,4,4],
 [5,6,7],
 [6,7,8],
 [7,8,8],
 [8,8,8]]

Как можно Я достигаю этого с эффективной нарезки вместо для L oop? Спасибо.

Ответы [ 3 ]

2 голосов
/ 18 января 2020

Аналогичный подход @hpaulj с использованием некоторых numpy встроенных функций

import numpy as np


samples = [[1,2,3,4],[5,6,7,8]]
ws = 3 #window size

# add padding
samples = [s + [s[-1]]*(ws-1) for s in samples]

# rolling window function for arrays
def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1]-window+1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)


result = sum([rolling_window(np.array(s), ws).tolist() for s in samples ], [])

result
[[1, 2, 3],
 [2, 3, 4],
 [3, 4, 4],
 [4, 4, 4],
 [5, 6, 7],
 [6, 7, 8],
 [7, 8, 8],
 [8, 8, 8]]
1 голос
/ 18 января 2020

A python подход списка:

In [201]: order = [1,3,2,3,5,8]                                                                  
In [202]: samples = [[1,2,3,4],[5,6,7,8]]

разверните выборки, чтобы решить проблему заполнения:

In [203]: samples = [row+([row[-1]]*n) for row in samples]                                       
In [204]: samples                                                                                
Out[204]: [[1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 8, 8, 8]]

определите функцию:

def foo(i, samples):
    for row in samples:
        try:
            j = row.index(i)
        except ValueError:
            continue 
        return row[j:j+n]
In [207]: foo(3,samples)                                                                         
Out[207]: [3, 4, 4]
In [208]: foo(9,samples)  # non-found case isn't handled well

для всех элементов заказа:

In [209]: [foo(i,samples) for i in order]                                                        
Out[209]: [[1, 2, 3], [3, 4, 4], [2, 3, 4], [3, 4, 4], [5, 6, 7], [8, 8, 8]]
0 голосов
/ 30 января 2020

У меня есть простой oneliner:

import numpy as np 
samples = np.array([[1,2,3,4],[5,6,7,8]]) 
n,d = samples.shape 
ws = 3

result = samples[:,np.minimum(np.arange(d)[:,None]+np.arange(ws)[None,:],d-1)]

Выход:

Нет l oop, только трансляция. Это делает его, вероятно, наиболее эффективным способом сделать это. Размерность вывода не совсем то, что вы просили, но это легко исправить с помощью простого np.reshape

[[[1 2 3]
  [2 3 4]
  [3 4 4]
  [4 4 4]]
 [[5 6 7]
  [6 7 8]
  [7 8 8]
  [8 8 8]]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...