Более питонический способ нарезать переменное расстояние от конца в массивах - PullRequest
0 голосов
/ 24 мая 2018

Мне интересно, есть ли лучший способ обрезки / вырезания массива с конца, но программным способом.Это означает, что размер обрезки на самом деле может быть 0, и у меня есть несколько измерений, например, 5-мерный тензор.

Вот простой пример в 2D:

# This is just to have some dummy data
import numpy as np
A = np.random.rand( 10,5)

# The easy standard case:
ix = 1
iy = 1
B = A [ ix:-ix , iy:-iy]   # This works

# Now the trickier case, where I'm looking for a pythonic way of doing it.
iy = 0
# Using the code from above, does not what I want => 2nd dim ==0 
C1 = A [ ix:-ix , iy:-iy]

# The next line gives the result that I want but hard coded
C2 = A [ ix:-ix ,   :   ]

# The next line also gives me what I want, but gets completely unreadable
# for real variable names and multiple dimensions
C3 = A [ ix:A.shape[0]-ix : iy:A.shape[1]-iy] 


# Is there something like this in numpy, similar to Matlab?
C4 = A [ ix:end-ix     , iy:end-iy ]
C5 = A [ ix:np.end-ix  , iy : np.end-iy ]

Я знаю, что это не таквыглядит плохо для 2D, но если у вас несколько измерений и реальных имен переменных, код легко испортится.Так есть ли что-то вроде «конца» от Matlab здесь, в python, или какой-то другой более питонский способ?

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Вы должны использовать slice(None).Для удобства чтения вы можете обернуть это в простую функцию:

def s(k):
    return slice(None) if k==0 else slice(k, -k)

C1 = A [ s(ix) , s(iy) ]
0 голосов
/ 24 мая 2018

Там нет end.Лучшее, что вы можете сделать, - это обернуть вещи во вспомогательную функцию:

def crop(arr, *crop_lengths):
    if len(crop_lengths) > arr.ndim:
        raise TypeError('Not enough dimensions to crop.')
    slices = [slice(i, axis_len-i) for (i, axis_len) in zip(crop_lengths, arr.shape)]
    return arr[tuple(slices)]

Пример использования:

ix = 1
iy = 0
cropped = crop(A, ix, iy)
...