Generalise slicing operation in a NumPy array
Here's the extension to handle generic ndarrays -
def indices_merged_arr_generic(arr, arr_pos="last"):
n = arr.ndim
grid = np.ogrid[tuple(map(slice, arr.shape))]
out = np.empty(arr.shape + (n+1,), dtype=np.result_type(arr.dtype, int))
if arr_pos=="first":
offset = 1
elif arr_pos=="last":
offset = 0
else:
raise Exception("Invalid arr_pos")
for i in range(n):
out[...,i+offset] = grid[i]
out[...,-1+offset] = arr
out.shape = (-1,n+1)
return out
Sample runs
2D case :
In [252]: arr
Out[252]:
array([[37, 32, 73],
[95, 80, 97]])
In [253]: indices_merged_arr_generic(arr)
Out[253]:
array([[ 0, 0, 37],
[ 0, 1, 32],
[ 0, 2, 73],
[ 1, 0, 95],
[ 1, 1, 80],
[ 1, 2, 97]])
In [254]: indices_merged_arr_generic(arr, arr_pos='first')
Out[254]:
array([[37, 0, 0],
[32, 0, 1],
[73, 0, 2],
[95, 1, 0],
[80, 1, 1],
[97, 1, 2]])
3D case :
In [226]: arr
Out[226]:
array([[[35, 45, 33],
[48, 38, 20],
[69, 31, 90]],
[[73, 65, 73],
[27, 51, 45],
[89, 50, 74]]])
In [227]: indices_merged_arr_generic(arr)
Out[227]:
array([[ 0, 0, 0, 35],
[ 0, 0, 1, 45],
[ 0, 0, 2, 33],
[ 0, 1, 0, 48],
[ 0, 1, 1, 38],
[ 0, 1, 2, 20],
[ 0, 2, 0, 69],
[ 0, 2, 1, 31],
[ 0, 2, 2, 90],
[ 1, 0, 0, 73],
[ 1, 0, 1, 65],
[ 1, 0, 2, 73],
[ 1, 1, 0, 27],
[ 1, 1, 1, 51],
[ 1, 1, 2, 45],
[ 1, 2, 0, 89],
[ 1, 2, 1, 50],
[ 1, 2, 2, 74]])
Numpy array slicing to return sliced array and corresponding array indices
You can use numpy's slice np.s_[]
with a tiny bit of gymnastics to get the indices you are looking for:
slc = np.s_[:, ::3]
shape = original.shape
ix = np.unravel_index(np.arange(np.prod(shape)).reshape(shape)[slc], shape)
>>> ix
(array([[0, 0],
[1, 1]]),
array([[0, 3],
[0, 3]]))
>>> original[ix]
array([[5, 3],
[8, 6]])
>>> original[slc]
array([[5, 3],
[8, 6]])
Note that this works with slices that have some reverse direction:
slc = np.s_[:, ::-2]
# ... (as above)
>>> ix
(array([[0, 0, 0],
[1, 1, 1]]),
array([[4, 2, 0],
[4, 2, 0]]))
>>> np.array_equal(original[ix], original[slc])
True
Using a string to define Numpy array slice
you can do something like:
var1="img"
prescan_area_def = "[:, :20]"
and to use eval
prescan_area=eval(var1+prescan_area_def)
Selecting multiple slices from a numpy array at once
You can use the indexes to select the rows you want into the appropriate shape.
For example:
data = np.random.normal(size=(100,2,2,2))
# Creating an array of row-indexes
indexes = np.array([np.arange(0,5), np.arange(1,6), np.arange(2,7)])
# data[indexes] will return an element of shape (3,5,2,2,2). Converting
# to list happens along axis 0
data_extractions = list(data[indexes])
np.all(data_extractions[1] == data[1:6])
True
The final comparison is against the original data.
Indexing a numpy array using a numpy array of slices
Your slices produce 2x6 and 2x3 arrays.
In [36]: subslice=slices[:2,1:3]
In [37]: subslice[0,0]
Out[37]: array([slice(0, 2, None), slice(6, 12, None)], dtype=object)
In [38]: ar[tuple(subslice[0,0])]
Out[38]:
array([[ 6, 7, 8, 9, 10, 11],
[21, 22, 23, 24, 25, 26]])
My numpy version expects me to turn the subslice
into a tuple. This is the same as
ar[slice(0,2), slice(6,12)]
ar[:2, 6:12]
That's just the basic syntax of indexing and slicing. ar
is 2d, so ar[(i,j)]
requires a 2 element tuple - of slices, lists, arrays, or integers. It won't work with an array of slice objects.
How ever it is possible to concatenate the results into a larger array. That can be done after indexing or the slices can be converted into indexing lists.
np.bmat
for example concatenates together a 2d arangement of arrays:
In [42]: np.bmat([[ar[tuple(subslice[0,0])], ar[tuple(subslice[0,1])]],
[ar[tuple(subslice[1,0])],ar[tuple(subslice[1,1])]]])
Out[42]:
matrix([[ 6, 7, 8, 9, 10, 11, 12, 13, 14],
[21, 22, 23, 24, 25, 26, 27, 28, 29],
[36, 37, 38, 39, 40, 41, 42, 43, 44],
[51, 52, 53, 54, 55, 56, 57, 58, 59]])
You could generalize this. It just uses hstack
and vstack
on the nested lists. The result is np.matrix
but can be converted back to array
.
The other approach is to use tools like np.arange
, np.r_
, np.xi_
to create index arrays. It'll take some playing around to generate an example.
To combine the [0,0] and [0,1] subslices:
In [64]: j = np.r_[subslice[0,0,1],subslice[0,1,1]]
In [65]: i = np.r_[subslice[0,0,0]]
In [66]: i,j
Out[66]: (array([0, 1]), array([ 6, 7, 8, 9, 10, 11, 12, 13, 14]))
In [68]: ix = np.ix_(i,j)
In [69]: ix
Out[69]:
(array([[0],
[1]]), array([[ 6, 7, 8, 9, 10, 11, 12, 13, 14]]))
In [70]: ar[ix]
Out[70]:
array([[ 6, 7, 8, 9, 10, 11, 12, 13, 14],
[21, 22, 23, 24, 25, 26, 27, 28, 29]])
Or with i = np.r_[subslice[0,0,0], subslice[1,0,0]]
, ar[np.ix_(i,j)]
produces the 4x9 array.
Slice 1D Array in Numpy without loop
If you're just after the first two characters from each hex value, one option is to recast your array to a dtype
of '|S2'
:
>>> x.astype('|S2')
array(['83', '83', '83', '84', '84', '84', '83', '85', '85', '83'],
dtype='|S2')
This idea can be generalised to return the first n
characters from each string.
Arbitrary slicing of string arrays is much more difficult to do in NumPy. Answers on this Stack Overflow page explain why it isn't the best tool for strings but show what can be possible.
Alternatively, the Pandas library facilitates fast vectorized operations (being built on top of NumPy). It has a number of very useful string operations which makes slicing a whole lot simpler than plain NumPy:
>>> import pandas as pd
>>> s = pd.Series(x)
>>> s.str.slice(2, 9)
0 8383747
1 83835F6
2 8383848
3 84835C5
4 8484787
5 8484505
6 8383757
7 8484555
8 8584535
9 8383848
dtype: object
New array from existing one, 2 column begin indexes of line/colum from the existing, third being values
You can create a meshgrid
of 2D coordinates for the rows and columns, then unroll these into 1D arrays. You can then concatenate these two arrays as well as the unrolled version of t
into one final matrix:
import numpy as np
(Y, X) = np.meshgrid(np.arange(t.shape[1]), np.arange(t.shape[0]))
db = np.column_stack((X.ravel(), Y.ravel(), t.ravel()))
Example run
In [9]: import numpy as np
In [10]: t = np.array([[0, 2.5],
...: [0, 0]])
In [11]: (Y, X) = np.meshgrid(np.arange(t.shape[1]), np.arange(t.shape[0]))
In [12]: db = np.column_stack((X.ravel(), Y.ravel(), t.ravel()))
In [13]: db
Out[13]:
array([[ 0. , 0. , 0. ],
[ 0. , 1. , 2.5],
[ 1. , 0. , 0. ],
[ 1. , 1. , 0. ]])
Most concise way to get complementary slice in numpy
Here's one concise way with np.r_
to generate those indices and then indexing into the input array -
A[np.r_[:start,stop:len(A)]]
Related Topics
How to Create a Decorator That Can Be Used Either with or Without Parameters
Python 2.X Gotchas and Landmines
Can Pandas Plot a Histogram of Dates
Flask-Sqlalchemy Update a Row's Information
"Private" (Implementation) Class in Python
Split Views.Py in Several Files
Pygame Tic Tak Toe Logic? How Would I Do It
How to Extract a Url from a String Using Python
Check If a Given Key Already Exists in a Dictionary and Increment It
Checking If Object on Ftp Server Is File or Directory Using Python and Ftplib
Differencebetween JSON.Load() and JSON.Loads() Functions
Curses Alternative for Windows
How to Add a Custom Loglevel to Python's Logging Facility
Python Library 'Unittest': Generate Multiple Tests Programmatically
Difference(S) Between Merge() and Concat() in Pandas