Slicing at runtime - python

can someone explain me how to slice a numpy.array at runtime?
I don't know the rank (number of dimensions) at 'coding time'.
A minimal example:
import numpy as np
a = np.arange(16).reshape(4,4) # 2D matrix
targetsize = [2,3] # desired shape
b_correct = dynSlicing(a, targetsize)
b_wrong = np.resize(a, targetsize)
print a
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
print b_correct
[[0 1 2]
[4 5 6]]
print b_wrong
[[0 1 2]
[3 4 5]]
And my ugly dynSlicing():
def dynSlicing(data, targetsize):
ndims = len(targetsize)
if(ndims==1):
return data[:targetsize[0]],
elif(ndims==2):
return data[:targetsize[0], :targetsize[1]]
elif(ndims==3):
return data[:targetsize[0], :targetsize[1], :targetsize[2]]
elif(ndims==4):
return data[:targetsize[0], :targetsize[1], :targetsize[2], :targetsize[3]]
Resize() will not do the job since it flats the array before dropping elements.
Thanks,
Tebas

Passing a tuple of slice objects does the job:
def dynSlicing(data, targetsize):
return data[tuple(slice(x) for x in targetsize)]

Simple solution:
b = a[tuple(map(slice,targetsize))]

You can directly 'change' it. This is due to the nature of arrays only allowing backdrop.
Instead you can copy a section, or even better create a view of the desired shape:
Link

Related

Creating a numpy matrix from a 1dim numpy array by performing computation on itself?

I have a numpy array 'arr' of shape (100000,). I need to create a numpy matrix 'res_matrix' of shape 100000X100000 such that
for i in range(res_matrix.shape[0]):
for j in range(res_matrix.shape[1]):
res_matrix[i][j]= arr[i]*arr[j]
Sample input/output
arr=[1 2 4]
Output:
res_matrix:
[[1 2 4]
[2 4 18]
[4 8 16]]
Is there way to do vectorize this operation, to reduce the computation time of calculating 00000X100000 in loop?
There are a few ways you can get an outer multiplication.
arr = np.array([1,2,4])
#Using Multiply outer
print(np.multiply.outer(arr, arr)) #As suggested by Warren
#Using broadcasting
print(arr[:,None] * arr[None,:]) #(3,1) * (1,3)
[[ 1 2 4]
[ 2 4 8]
[ 4 8 16]]
[[ 1 2 4]
[ 2 4 8]
[ 4 8 16]]
​
Note, the output is still a very large matrix for storing in memory. Depending on what you need it for, I would advise considering something like a generator function. Let me know how you are going to use this matrix and I could suggest more memory efficient methods.

View function is not creating view correctly

I have created numpy array named a, then created another array b by view of a. Ex. b=a.view().
However, b.base is a is giving False instead of True. Please help.
a=np.arange(6).reshape(2,3)
b=a.view()
print(b.base is a) # Expected True, actual was False
Because it is a view of the original array which is returned by numpy.arange(6)
import numpy as np
a = np.arange(6)
b = a.reshape(2,3)
c = b.view()
print(c.base is a, b.base is a)
If you will use print statements,You will be very clear about this:-
import numpy as np
a=np.arange(6).reshape(2,3)
print(a)
b=a.view()
print(b.base)
The outputs of the print statements will look like
[[0 1 2]
[3 4 5]]
[0 1 2 3 4 5]
You can clearly see the difference.To make the output True you can use this:-
import numpy as np
a=np.arange(6)
newa=a.reshape(2,3)
print(a)
b=newa.view()
print(b.base)
print(b.base is a)
The Corresponding output will be:-
[0 1 2 3 4 5]
[0 1 2 3 4 5]
True

How to reorder coordinate values using the euclidian distance in Python?

I want to reorder the coordinate value based on the euclidean distance .
For example I have coordinates:
1 2
2 1
1 3
1 9
6 9
3 5
6 8
4 5
7 9
I have got euclidean distance of first coordinate with other coordinate:
With the following code:
with open("../data comparision project/testfile.txt") as f:
# for splitting the text file into to lists of list
my_list = [[x for x in line.strip().split(' ')] for line in f
index = 0
# empty list to store distances.
euclidean_distance_list = []
for list_of_item in my_list:
plot1=my_list[0]
plot2=my_list[index]
euclidean_distance=math.sqrt((float(plot1[0])-float(plot2[0]))**2 + (float(plot1[1])-float(plot2[1]))**2)
index=index+1
# Out of for loop
sorted_list=sorted(euclidean_distance_list)
print(sorted_list)
This generates the following output:
[0.0, 1.0, 1.4142135623730951, 3.605551275463989, 4.242640687119285, 7.0, 7.810249675906654, 8.602325267042627, 9.219544457292887]
Now I want to reorder the original coordinate value based on the these distances such that it will be:
1 2
1 3
1 9
2 1
3 5
4 5
6 8
6 9
7 9
Can anyone help me with python code.I have caluclated distance but unable to get list with sorted coordinate vlaues.
You want to sort the list based on a custom comparator.
Check out the key optional argument to the sort function. You can supply a custom comparator as key.
https://docs.python.org/3/howto/sorting.html
To fill in a bit more detail - supposing that you already wrote the function:
def euclidean_distance(a, b):
# does the math and gives the distance between coordinates a and b.
# If you got the values some other way - better reorganize the code
# first so that you have a function like this :)
We can use functools.partial to make a function for distances from a given point:
distance_from_a = functools.partial(euclidean_distance, points[0])
and then the rest of the logic is built into Python's native sorting functionality:
sorted(points, key=distance_from_a)
You can perform a custom sort by doing something like this assuming you are using numpy:
import numpy as np
def euclidian_distance(a, b):
return np.linalg.norm(a - b)
coords = np.array([[1,2],
[2,1],
[1,3],
[1,9],
[6,9],
[3,5],
[6,8],
[4,5],
[7,9]])
coords = sorted(coords, key=lambda point: euclidian_distance(point, coords[0]))
print(np.matrix(coords)) # matrix is only for formatting for readability purposes
Output:
[[1 2]
[1 3]
[2 1]
[3 5]
[4 5]
[1 9]
[6 8]
[6 9]
[7 9]]
To explain why the above output is different from the OP's. It's because the OP's example output is not actually ordered by distance like they described they wanted.

replace element by element different arrays

I have an array :
a = np.array([1,2,3,4,5,6,7,8])
The array may be reshaped to a = np.array([[1,2,3,4],[5,6,7,8]]), whatever is more convenient.
Now, I have an array :
b = np.array([[11,22,33,44], [55,66,77,88]])
I want to replace to each of these elements the corresponding elements from a.
The a array will always hold as many elements as b has.
So, array b will be :
[1,2,3,4], [5,6,7,8]
Note, that I must keep each b subarray dimension to (4,). I don't want to change it.So, the idx will take values from 0 to 3.I want to make a fit to every four values.
I am struggling with reshape, split,mask ..etc and I can't figure a way to do it.
import numpy as np
#a = np.array([[1,2,3,4],[5,6,7,8]])
a = np.array([1,2,3,4,5,6,7,8])
b = np.array([[11,22,33,44], [55,66,77,88]])
for arr in b:
for idx, x in enumerate(arr):
replace every arr[idx] with corresponding a value
For your current case, what you want is probably:
b, c = list(a.reshape(2, -1))
This isn't the cleanest, but it is a one-liner. Turn your 1D array into a 2D array with with the first dimension as 2 with reshape(2, -1), then list splits it along the first dimension so you can directly assign them to b, c
You can also do it with the specialty function numpy.split
b, c = np.split(a, 2)
EDIT: Based on accepted solution, vectorized way to do this is
b = a.reshape(b.shape)
The following worked for me:
i = 0
for arr in b:
for idx, x in enumerate(arr):
arr[idx] = a[i]
print(arr[idx])
i += 1
Output (arr[idx]): 1 2 3 4 5 6 7 8
If you type print(b) it'll output [[1 2 3 4] [5 6 7 8]]
b = a[:len(a)//2]
c = a[len(a)//2:]
Well, I'm quite new to Python but this worked for me:
for i in range (0, len(a)//2):
b[i] = a[i]
for i in range (len(a)//2,len(a)):
c[i-4] = a[i]
by printing the 3 arrays I have the following output:
[1 2 3 4 5 6 7 8]
[1 2 3 4]
[5 6 7 8]
But I would go for Daniel's solution (the split one): 1 liner, using numpy API, ...

the output of using np.empty_like in Python

While studying the NumPy package of Python, I tried the following code segment
import numpy as np
x = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
v = np.array([1,0,1])
y = np.empty_like(x)
print(y)
for i in range(4):
y[i,:] = x[i,:]+v
print "......."
print(y)
However, the first print(y) gives the output such as following, instead of all zero array. On the other side, the second print(y)generates the correct result as expected. I would like to know why.
[[ 72 0 0]
[ 0 2676 1346720256]
[1599357253 1950699087 10]
[1346524499 1163154497 242503250]]
.......
[[ 2 2 4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]
You want zeros_like. empty_like gives an array filled with who-knows-what, so it doesn't have to spend time filling it with zeros.

Categories