Moving window with complete boundary in Python - python

I have been using rolling/moving windows lately and all implementations I have seen so far ignore values contained in the boundaries of the array if these values can not be placed in a complete window. For example, assume you have this array:
import numpy as np
np.arange(10*10).reshape(10,10)
Out[1]:
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
Using view_as_windows from scikit-image, you can see there are several elements (last two columns and last two rows) that can't be placed inside another 4x4 window:
from skimage.util import view_as_windows
view_as_windows(np.arange(10*10).reshape(10,10), (4,4),4)
Out[14]:
array([[[[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23],
[30, 31, 32, 33]],
[[ 4, 5, 6, 7],
[14, 15, 16, 17],
[24, 25, 26, 27],
[34, 35, 36, 37]]],
[[[40, 41, 42, 43],
[50, 51, 52, 53],
[60, 61, 62, 63],
[70, 71, 72, 73]],
[[44, 45, 46, 47],
[54, 55, 56, 57],
[64, 65, 66, 67],
[74, 75, 76, 77]]]])
I think sklearn.feature_extraction.image.extract_patches_2d behaves in the same way. As far as I understand, both use stride tricks to obtain memory views of the array. However, I'd like to be able to obtain partial windows even if they don't have the same size.

Related

Extract an array of numbers from a Python array

Suppose I have a 10x10 Python array, M. I would like to extract the 3x3 array with the values of the rows [2,3,5], and columns [2,3,5]. How do I do this? I would like to obtain the equivalent of M[0:3,0:3] but using coordinates [2,3,5] instead of [0,1,2].
I have tried M[[2,3,5],[2,3,5]], but this produces three values, not a 3x3 array.
You could .take() twice
>>> a = np.arange(100).reshape(10,10)
>>> a
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
>>> np.take(np.take(a, [2,3,5], axis=1), [2,3,5], axis=0)
array([[22, 23, 25],
[32, 33, 35],
[52, 53, 55]])
One option to use is numpy.ix_.
It should be as simple as M[np.ix_([2, 3, 5], [2, 3, 5])].

How to split a large list into rows?

I have a problem with my list. My task is generate the big with the random list which consist of 10 smaller list with 10 random numbers. I have a correct code generate 10x random list in one big list, but now I need to separate each smaller list because each have to be in the new line.
This is my code:
def generate_random_number_list_10(len_of_elements):
single_list_of_10_random_numbers=[]
for _variable_1 in range (len_of_elements):
random_number=random.randint(1,100)
single_list_of_10_random_numbers.append(random_number)
return single_list_of_10_random_numbers
def generate_random_number_list_10x10_1(amount_of_lists):
main_list=[]
for _variable_1 in range (amount_of_lists):
singlelist=generate_random_number_list_10(5)
main_list.append(singlelist)
print(main_list)
generate_random_number_list_10x10_1(10)
this is my result:
[[45, 35, 90, 12, 13, 80, 33, 17, 50, 47], [33, 92, 55, 26, 60, 51, 78, 62, 35, 3], [87, 79, 4, 10, 57, 8, 59, 75, 59, 85], [33, 15, 10, 100, 79, 74, 57, 46, 14, 37], [93, 15, 29, 35, 54, 24, 24, 39, 21, 62], [55, 90, 8, 33, 6, 29, 19, 5, 97, 93], [51, 27, 14, 18, 45, 29, 83, 94, 34, 91], [66, 92, 40, 36, 72, 46, 77, 77, 89, 64], [89, 84, 36, 14, 96, 81, 57, 65, 51, 56], [97, 100, 94, 58, 26, 18, 6, 1, 88, 46]]
but I need something like this:
[45, 35, 90, 12, 13, 80, 33, 17, 50, 47]
[33, 92, 55, 26, 60, 51, 78, 62, 35, 3]
etc...
You can unpack them and use sep parameter in print.
print(*list_of_lists,sep='\n')
[45, 35, 90, 12, 13, 80, 33, 17, 50, 47]
[33, 92, 55, 26, 60, 51, 78, 62, 35, 3]
[87, 79, 4, 10, 57, 8, 59, 75, 59, 85]
[33, 15, 10, 100, 79, 74, 57, 46, 14, 37]
[93, 15, 29, 35, 54, 24, 24, 39, 21, 62]
[55, 90, 8, 33, 6, 29, 19, 5, 97, 93]
[51, 27, 14, 18, 45, 29, 83, 94, 34, 91]
[66, 92, 40, 36, 72, 46, 77, 77, 89, 64]
[89, 84, 36, 14, 96, 81, 57, 65, 51, 56]
[97, 100, 94, 58, 26, 18, 6, 1, 88, 46]
one way will be to print the numbers once they have been produced:
def generate_random_number_list_10x10_1(amount_of_lists):
for _variable_1 in range (amount_of_lists):
print(generate_random_number_list_10(amount_of_lists))
generate_random_number_list_10x10_1(10)
output:
[49, 48, 9, 53, 17, 11, 52, 29, 72, 18]
[1, 3, 35, 73, 3, 14, 75, 87, 43, 4]
[61, 89, 13, 76, 41, 20, 79, 29, 59, 84]
[13, 25, 34, 6, 89, 60, 44, 49, 64, 96]
[49, 70, 12, 12, 49, 74, 58, 94, 33, 16]
[36, 73, 37, 51, 25, 43, 91, 67, 94, 56]
[90, 45, 40, 40, 14, 82, 39, 54, 27, 55]
[4, 52, 78, 53, 57, 31, 17, 31, 2, 38]
[91, 67, 57, 14, 33, 25, 8, 93, 37, 44]
[59, 60, 48, 44, 3, 70, 85, 13, 38, 13]
pay attention to your question, it is a difference between what your code generates and what you say it does, singlelist=generate_random_number_list_10(5) will give you lists with 5 elemnts inside

pick by index in numpy

Suppose two arrays
ind =
array([[1, 3, 2, 4, 0],
[0, 1, 3, 2, 4],
[3, 4, 2, 0, 1]])
x =
array([[[24, 97, 28, 57, 59],
[97, 67, 94, 77, 50],
[56, 89, 25, 55, 76],
[88, 21, 1, 50, 24]],
[[54, 83, 64, 81, 12],
[89, 49, 15, 26, 97],
[94, 97, 32, 55, 79],
[24, 63, 63, 15, 40]],
[[41, 99, 84, 64, 21],
[12, 9, 85, 43, 28],
[75, 98, 48, 10, 0],
[93, 94, 37, 22, 63]]])
I want to reorder second array according to first array.(first array is the index)
So, maybe the result will be like below.
array([[[97, 57, 28, 59, 24],
[67, 77, 94, 50, 97],
[89, 55, 25, 76, 56],
[21, 50, 1, 24, 88]],
[[54, 83, 81, 64, 12],
[89, 49, 26, 15, 97],
[94, 97, 55, 32, 79],
[24, 63, 15, 63, 40]],
[[64, 21, 84, 41, 99],
[43, 28, 85, 12, 9],
[10, 0, 48, 75, 98],
[22, 63, 37, 93, 94]]])
# x[0]s are reordered by ind[0] and so on.
And is this possible with np.take?
It is easy using take_along_axis:
>>> np.take_along_axis(x, ind[:, None, :], 2)
array([[[97, 57, 28, 59, 24],
[67, 77, 94, 50, 97],
[89, 55, 25, 76, 56],
[21, 50, 1, 24, 88]],
[[54, 83, 81, 64, 12],
[89, 49, 26, 15, 97],
[94, 97, 55, 32, 79],
[24, 63, 15, 63, 40]],
[[64, 21, 84, 41, 99],
[43, 28, 85, 12, 9],
[10, 0, 48, 75, 98],
[22, 63, 37, 93, 94]]])
If you are on pre 1.15 numpy, you can do:
>>> m,n,k = x.shape
>>> m,n,k = np.ogrid[:m, :n, :k]
>>> x[m,n,ind[:, None, :]]
array([[[97, 57, 28, 59, 24],
[67, 77, 94, 50, 97],
[89, 55, 25, 76, 56],
[21, 50, 1, 24, 88]],
[[54, 83, 81, 64, 12],
[89, 49, 26, 15, 97],
[94, 97, 55, 32, 79],
[24, 63, 15, 63, 40]],
[[64, 21, 84, 41, 99],
[43, 28, 85, 12, 9],
[10, 0, 48, 75, 98],
[22, 63, 37, 93, 94]]])

Ordering a list

I have a list like this,
M=[[75], [95, 64], [17, 47, 82], [18, 35, 87, 10], [20, 4, 82, 47, 65], [19,
1, 23, 75, 3, 34], [88, 2, 77, 73, 7, 63, 67], [99, 65, 4, 28, 6, 16, 70,
92], [41, 41, 26, 56, 83, 40, 80, 70, 33], [41, 48, 72, 33, 47, 32, 37, 16,
94, 29], [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14], [70, 11, 33, 28, 77,
73, 17, 78, 39, 68, 17, 57], [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27,
29, 48], [63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31], [4, 62,
98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23]]
and I would like to sort it by the largest number on the "zero" position for each element in the list for example,
M=[[75], [95, 64], [82, 47, 17], [87, 35, 18, 10].....]
I tried to use a key but it didnt work well also I didnt know why it didnt work well..Here the key
def Len(elem):
for i in range(16):
y=len(K[i])
return elem[y-1]
y=sorted(K,key=Len)
print(y)
Maybe I just didnt understand the key function.
Thanks
Just use sorted (or list.sort) without a key. They already sort lexicographically.
>>> sorted(M, reverse=True)
[[99, 65, 4, 28, 6, 16, 70, 92], [95, 64], [91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48], [88, 2, 77, 73, 7, 63, 67], [75], [70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57], [63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31], [53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14], [41, 48, 72, 33, 47, 32, 37, 16, 94, 29], [41, 41, 26, 56, 83, 40, 80, 70, 33], [20, 4, 82, 47, 65], [19, 1, 23, 75, 3, 34], [18, 35, 87, 10], [17, 47, 82], [4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23]]
edit:
Sorting the lists individually:
>>> [sorted(sublist, reverse=True) for sublist in M]
[[75], [95, 64], [82, 47, 17], [87, 35, 18, 10], [82, 65, 47, 20, 4], [75, 34, 23, 19, 3, 1], [88, 77, 73, 67, 63, 7, 2], [99, 92, 70, 65, 28, 16, 6, 4], [83, 80, 70, 56, 41, 41, 40, 33, 26], [94, 72, 48, 47, 41, 37, 33, 32, 29, 16], [97, 91, 71, 65, 53, 52, 51, 44, 43, 25, 14], [78, 77, 73, 70, 68, 57, 39, 33, 28, 17, 17, 11], [91, 91, 71, 58, 52, 50, 48, 43, 38, 29, 27, 17, 14], [89, 87, 73, 69, 68, 67, 66, 63, 53, 40, 31, 30, 16, 4], [98, 98, 93, 73, 70, 62, 60, 53, 38, 27, 23, 23, 9, 4, 4]]
Try operator itemgetter function as key.
Like this:
from operator import itemgetter
sorted(K,key=itemgetter(0))
try using index of each element :
for i in M:
M[M.index(i)]=sorted(i,reverse=True)

Selecting every n indices of an array

If I have an array that is 100 elements in length, what is the most Pythonic way to get every n indices. For example, if I wanted every 5 indices of an array a, how could I get an array b=[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14],...], where each element of b is a sub-array of every 5 indices?
You simply want to reshape your array:
>>> arr = np.arange(100)
>>> arr
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])
>>> arr.reshape(-1, 5)
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59],
[60, 61, 62, 63, 64],
[65, 66, 67, 68, 69],
[70, 71, 72, 73, 74],
[75, 76, 77, 78, 79],
[80, 81, 82, 83, 84],
[85, 86, 87, 88, 89],
[90, 91, 92, 93, 94],
[95, 96, 97, 98, 99]])
Note, I used -1 on the first axis, numpy is smart enough to "solve the equation" as long as you give it every other axis explicitly. You could have, of course, done this completely explicitly:
>>> arr.reshape(20, 5)
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59],
[60, 61, 62, 63, 64],
[65, 66, 67, 68, 69],
[70, 71, 72, 73, 74],
[75, 76, 77, 78, 79],
[80, 81, 82, 83, 84],
[85, 86, 87, 88, 89],
[90, 91, 92, 93, 94],
[95, 96, 97, 98, 99]])
Update:
If you are using lists, a very pythonic way to do it:
size = 5 # the number of elements of each sublists
l = list(range(100))
result = [l[step:step + size] for step in range(0, len(l), size)]
Ouput:
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9],
[10, 11, 12, 13, 14], [15, 16, 17, 18, 19],
[20, 21, 22, 23, 24], [25, 26, 27, 28, 29],
[30, 31, 32, 33, 34], [35, 36, 37, 38, 39],
[40, 41, 42, 43, 44], [45, 46, 47, 48, 49],
[50, 51, 52, 53, 54], [55, 56, 57, 58, 59],
[60, 61, 62, 63, 64], [65, 66, 67, 68, 69],
[70, 71, 72, 73, 74], [75, 76, 77, 78, 79],
[80, 81, 82, 83, 84], [85, 86, 87, 88, 89],
[90, 91, 92, 93, 94], [95, 96, 97, 98, 99]]
>>> L = range(100)
>>> step = 5
>>> [L[i:i+step] for i in range(0, len(L), step)]
[[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34],
[35, 36, 37, 38, 39],
[40, 41, 42, 43, 44],
[45, 46, 47, 48, 49],
[50, 51, 52, 53, 54],
[55, 56, 57, 58, 59],
[60, 61, 62, 63, 64],
[65, 66, 67, 68, 69],
[70, 71, 72, 73, 74],
[75, 76, 77, 78, 79],
[80, 81, 82, 83, 84],
[85, 86, 87, 88, 89],
[90, 91, 92, 93, 94],
[95, 96, 97, 98, 99]]
Seems a natural way to do it to me.

Categories

Resources