numpy slicing select parts of array - python

I have a one dimensional array from which I would like to create a new array containing only parts of user wished sizes of the beginning, the middle, and the end of the former.
import numpy
a = range(10)
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
I would like b to be equal to:
b
array([0, 1, 2, 5, 6, 7, 9])
Assuming that b is constructed of the concatenation of a[:3], a[5:6], and a[9].
I can of course use things such as np.concatenate, but is there a way to do that with slicing method, or anything else in one line?

One way is to create an array of the indices you want to index your array with:
import numpy
a = numpy.arange(10)
i = numpy.array([0, 1, 2, 5, 6, 7, 9]) # An array containing the indices you want to extract
print a[i] # Index the array based on the indices you selected
OUTPUT
[0 1 2 5 6 7 9]

I found a solution:
import numpy as np
a = range(10)
b = np.hstack([a[:3], a[5:6], a[9])
b
array([0, 1, 2, 5, 6, 7, 9])
but does slicing allow such a move?

Related

How to reverse a numpy array and then also switch each 'pair' of positions?

For example, how would you do this sequence of operations on a np 1D array, x:
[1,2,3,4,5,6,7,8]
[8,7,6,5,4,3,2,1]
[7,8,5,6,3,4,1,2]
The transition from state 1 to state 2 can be done with numpy.flip(x):
x = numpy.flip(x)
How can you go from this intermediate state to the final state, in which each 'pair' of positions switches positions
Notes: this is a variable length array, and will always be 1D
It is assumed that the length is always even. At this time, you only need to reshape, reverse and flatten:
>>> ar = np.arange(1, 9)
>>> ar.reshape(-1, 2)[::-1].ravel()
array([7, 8, 5, 6, 3, 4, 1, 2])
This always creates a copy, because the elements in the original array cannot be continuous after transformation, but ndarray.ravel() must create a continuous view.
If it is necessary to transition from state 2 to state 3:
>>> ar = ar[::-1]
>>> ar # state 2
array([8, 7, 6, 5, 4, 3, 2, 1])
>>> ar.reshape(-1, 2)[:, ::-1].ravel()
array([7, 8, 5, 6, 3, 4, 1, 2])
This should work (assumin you have a even number of elements, otherwise you might want to check this before)
x = x.reshape((len(x)//2, 2)) #split in two wolumns
x[:,0], x[:,1] = x[:,1], x[:,0].copy() # switch the columns
x = x.reshape(2*len(x)) # reshape back in a 1D array
You can do:
import numpy as np
arr = np.array([8,7,6,5,4,3,2,1])
result = np.vstack((arr[1::2], arr[::2])).T.flatten()
output:
array([7, 8, 5, 6, 3, 4, 1, 2])

Can I put a condition for y-index in numpy.where?

I have a 2D numpy array taken from a segmentation. Therefore, it's an image like the one in the right:
https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQwYeYOHk0xUJ6vBd_g8Xn1LxMON0g2qHpf_TPJx6h7IM5nG2OXeKtDuCcjgN9mqFtLB5c&usqp=CAU
The colours you see means that each value of my array can only have a value in a limit range (e.g., green is 5, orange is 7...). Now I would like to change all the cells that contains a 5 (green) and its y-coordinate is up to a value I want (e.g. only apply the later condition up to row 400). What's the most optimized algorithm to do this?
I guess that you can use something like:
np.where(myarray == 5, myarray, valueIwant)
but I will need to apply the condition for y-index...
Your current example seems to be misaligned with what you want:
a = np.array([1, 1, 2, 2, 3, 3])
np.where(a==2, a, 7)
produces:
array([7, 7, 2, 2, 7, 7])
If you want to replace 2 with some other value:
array([1, 1, 7, 7, 3, 3])
you can do this:
np.where(a==2, 7, a)
or
a[a==2] = 7
To replace only up to a certain value:
sub_array = a[:3]
sub_array[sub_array==2] = 7
a
array([1, 1, 7, 2, 3, 3])

pythonic way to get the (2,2) for every (4,4) block / grid in nxn numpy array [duplicate]

I am a beginner with numpy, and I am trying to extract some data from a long numpy array. What I need to do is start from a defined position in my array, and then subsample every nth data point from that position, until the end of my array.
basically if I had
a = [1,2,3,4,1,2,3,4,1,2,3,4....]
I want to subsample this to start at a[1] and then sample every fourth point from there, to produce something like
b = [2,2,2.....]
You can use numpy's slicing, simply start:stop:step.
>>> xs
array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4])
>>> xs[1::4]
array([2, 2, 2])
This creates a view of the the original data, so it's constant time. It'll also reflect changes to the original array and keep the whole original array in memory:
>>> a
array([1, 2, 3, 4, 5])
>>> b = a[::2] # O(1), constant time
>>> b[:] = 0 # modifying the view changes original array
>>> a # original array is modified
array([0, 2, 0, 4, 0])
so if either of the above things are a problem, you can make a copy explicitly:
>>> a
array([1, 2, 3, 4, 5])
>>> b = a[::2].copy() # explicit copy, O(n)
>>> b[:] = 0 # modifying the copy
>>> a # original is intact
array([1, 2, 3, 4, 5])
This isn't constant time, but the result isn't tied to the original array. The copy also contiguous in memory, which can make some operations on it faster.
Complementary to behzad.nouri's answer:
If you want to control the number of final elements and ensure it's always fixed to a predefined value (rather than controlling a fixed step in between subsamples) you can use numpy's linspace method followed by integer rounding.
For example, with num_elements=4:
>>> a
array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> choice = np.round(np.linspace(1, len(a)-1, num=4)).astype(int)
>>> a[choice]
array([ 2, 5, 7, 10])
Or, subsampling an array with final start/end points in general:
>>> import numpy as np
>>> np.round(np.linspace(0, len(a)-1, num=4)).astype(int)
array([0, 3, 6, 9])
>>> np.round(np.linspace(0, len(a)-1, num=15)).astype(int)
array([0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9])

how to delete multiple rows in an array

I have to delete last three rows of the array. It was list but I had to convert it into array so that I can use np.delete function
I tried np.delete function. It deletes column wise instead of row wise.
I want to delete row not column. When I change the axis to 1. it gives an error message of AxisError: axis 1 is out of bounds for array of dimension 1
featureStr2=np.delete(f, slice(3,-1), axis=0). I want to delete last 3 rows. Array looks like below
1 2 3 4 5
6 7 8 9 20
11 23 54 6 7
2 3 4 5 6 7
1 2 3 4 5
Out put of the code is. I want output to delete last 3 rows.
Don't delete in numpy. Deleting triggers a reallocation, which is expensive. The cheap (proper) solution is to just create a view using indexing:
arr = arr[:-3, ...]
you can drop rows by using pandas with drop, indexing and condition function
import numpy as np
import pandas as pd
df = ([1,2,3,4,5], [6,7,8,9,20],[11,23,54,6,7],[2,3,4,5,6,7],[1,2,3,4,5])
series = pd.DataFrame(df)
by using drop function
series1 = series.drop([2,3,4])
print(series1)
using index function
series1 = series.drop(series.index[2,3,4]
print(series1)
What you need is Axis and object:
Syntax: numpy.delete(arr, obj, axis=None)
object : is the row number or column number or a indices
Axis: 0 for the rows and 1 for the columns
e.g. i'm assuming your array looks like this.
a = np.array([[1,2,3,4,5], [2,4,5,6,7], [3,4,5,6,7], [5,7,8,9,1]])
>>> np.delete(a, [2,3], axis=0)
array([[1, 2, 3, 4, 5],
[2, 4, 5, 6, 7]])
P.S. for now np.delete doesn't support negative indices, in future it will , so i suggest you to get the indices of the rows you want to delete first and then pass it to obj in np.delete()
The simplest way is to just use basic indexing
>>>import numpy as np
>>>arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 20], [11, 23, 54, 6, 7],
[2, 3, 4, 6, 7],[1,2, 3, 4, 5]])
>>>arr = arr[:-3]
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 20]])
np.delete(arr, obj, axis=None) doesn't take in negative indices in its object argument
Also, if array size is large, then supplying index of every row, column or element to be deleted becomes tedious.
>>>np.delete(arr, [2,3,4], axis=0)
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 20]])
But by using np.s_ you can supply a slice to the function
>>>np.delete(arr, np.s_[2:5], axis=0)
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 20]])
You can supply negative indexing to np.s_
>>>np.delete(arr, np.s_[-3:], axis=0)
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 20]])

How can I merge rows in np matrix?

I've got a numpy matrix that has 2 rows and N columns, e.g. (if N=4):
[[ 1 3 5 7]
[ 2 4 6 8]]
The goal is create a string 1,2,3,4,5,6,7,8.
Merge the rows such that the elements from the first row have the even (1, 3, ..., N - 1) positions (the index starts from 1) and the elements from the second row have the odd positions (2, 4, ..., N).
The following code works but it isn't really nice:
xs = []
for i in range(number_of_cols):
xs.append(nums.item(0, i))
ys = []
for i in range(number_of_cols):
ys.append(nums.item(1, i))
nums_str = ""
for i in range(number_of_cols):
nums_str += '{},{},'.format(xs[i], ys[i])
Join the result list with a comma as a delimiter (row.join(','))
How can I merge the rows using built in functions (or just in a more elegant way overall)?
Specify F order when flattening (or ravel):
In [279]: arr = np.array([[1,3,5,7],[2,4,6,8]])
In [280]: arr
Out[280]:
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
In [281]: arr.ravel(order='F')
Out[281]: array([1, 2, 3, 4, 5, 6, 7, 8])
Joining rows can be done this way :
>>> a = np.arange(12).reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> np.hstack([a[i,:] for i in range(a.shape[0])])
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
Then it's simple to convert this array into string.
Here's one way of doing it:
out_str = ','.join(nums.T.ravel().astype('str'))
We are first transposing the array with .T, then flattening it with .ravel(), then converting each element from int to str, and then applying `','.join() to combine all the str elements
Trying it out:
import numpy as np
nums = np.array([[1,3,5,7],[2,4,6,8]])
out_str = ','.join(nums.T.ravel().astype('str'))
print (out_str)
Result:
1,2,3,4,5,6,7,8

Categories