Get more than one dimension with numpy take function - python

I've got a one dimensional array (n) called edges and want to insert the values by the index from the vertices array (n,3)
vertices = [[ 1.25, 4.321, -4], [2, -5, 3.32], [23.3, 43, 12], [32, 4, -23]]
edges = [1, 3, 2, 0]
result = [[2, -5, 3.32], [32, 4, -23], [23.3, 43, 12], [ 1.25, 4.321, -4]]
I tried np.take(vertices, edges) but It doesn't work for multi dimensional arrays.

take with axis parameter works
In [313]: vertices=np.array(vertices)
In [314]: edges=[1,3,2,0]
In [315]: np.take(vertices, edges,0)
Out[315]:
array([[ 2. , -5. , 3.32 ],
[ 32. , 4. , -23. ],
[ 23.3 , 43. , 12. ],
[ 1.25 , 4.321, -4. ]])
In [316]: vertices[edges,:]
Out[316]:
array([[ 2. , -5. , 3.32 ],
[ 32. , 4. , -23. ],
[ 23.3 , 43. , 12. ],
[ 1.25 , 4.321, -4. ]])

You can simply use indexing here:
vertices[edges]
# ^ ^ indexing
If you index with a list, then numpy will reshuffle the original matrix such that the highest dimension here follows the indices as specified by edges.
like:
>>> vertices = np.array([[ 1.25, 4.321, -4], [2, -5, 3.32], [23.3, 43, 12], [32, 4, -23]])
>>> edges = [1, 3, 2, 0]
>>> vertices[edges]
array([[ 2. , -5. , 3.32 ],
[ 32. , 4. , -23. ],
[ 23.3 , 43. , 12. ],
[ 1.25 , 4.321, -4. ]])
>>> vertices[edges].base is None
True
The fact that base is None means that this does not generate a view, it makes a copy of the matrix (with filtered/reordered rows). Changes you thus later make to the elements of vertices will not change the elements of the result of vertices[edges] (given you make the copy before altering vertices of course).

Related

how to reshape 3D to 2D ? but I don't want to lose the brackets in between?

I have this array
X = np.array([[-2, -1.9], [-3, -2], [-1, -1], [1, 1.5], [3, 2]])
once I insert a point
x = np.asarray([[20, 4.9]])
it becomes 3D
array([[[-2. , -1.9],
[-3. , -2. ],
[-1. , -1. ],
[ 1. , 1.5],
[ 3. , 2. ],
[20. , 4.9]]])
How to keep it always 2D even if I added points ?
Try this:
>>> X = np.array([[-2, -1.9], [-3, -2], [-1, -1], [1, 1.5], [3, 2]])
>>> x = np.asarray([[20, 4.9]])
>>> np.append(X,x,axis=0)
array([[-2. , -1.9],
[-3. , -2. ],
[-1. , -1. ],
[ 1. , 1.5],
[ 3. , 2. ],
[20. , 4.9]])
>>> np.insert(X, len(X), x, axis=0)
array([[-2. , -1.9],
[-3. , -2. ],
[-1. , -1. ],
[ 1. , 1.5],
[ 3. , 2. ],
[20. , 4.9]])
Edit answer base your comment: (Change 3D numpy.array to 2D numpy.array)
>>> Y = np.array([[[-2. , -1.9], [-3. , -2. ], [-1. , -1. ], [ 1. , 1.5], [ 3. , 2. ], [20. , 4.9]]])
>>> Y.shape
(1, 6, 2)
>>> Z = Y.reshape(Y.shape[1],Y.shape[2])
>>> Z.shape
(6, 2)
Update: (get numpy.array elements with another list)
>>> X = np.array([[-2, -1.9], [-3, -2], [-1, -1], [1, 1.5], [3, 2]])
>>> ex = [0,1,0,1]
>>> X[np.array(ex)]
array([[-2. , -1.9],
[-3. , -2. ],
[-2. , -1.9],
[-3. , -2. ]])
np.concatenate((X, x), axis=0)
result:
array([[-2. , -1.9],
[-3. , -2. ],
[-1. , -1. ],
[ 1. , 1.5],
[ 3. , 2. ],
[20. , 4.9]])

How do I combine two numpy arrays so for each row of the first array I append all rows from the second one?

I have the following numpy arrays:
theta_array =
array([[ 1, 10],
[ 1, 11],
[ 1, 12],
[ 1, 13],
[ 1, 14],
[ 2, 10],
[ 2, 11],
[ 2, 12],
[ 2, 13],
[ 2, 14],
[ 3, 10],
[ 3, 11],
[ 3, 12],
[ 3, 13],
[ 3, 14],
[ 4, 10],
[ 4, 11],
[ 4, 12],
[ 4, 13],
[ 4, 14]])
XY_array =
array([[ 44.0394952 , 505.81099922],
[ 61.03882938, 515.97253226],
[ 26.69851841, 525.18083012],
[ 46.78487831, 533.42309602],
[ 45.77188401, 545.42988355],
[ 81.12969132, 554.78767379],
[ 54.178463 , 565.8716283 ],
[ 41.58952084, 574.76827133],
[ 85.24956815, 585.1355127 ],
[ 80.73726733, 595.49446033],
[ 22.70625059, 605.59017175],
[ 40.66810604, 615.26308629],
[ 47.16694695, 624.39222332],
[ 48.72499541, 633.19846364],
[ 50.68589921, 643.72334885],
[ 38.42731134, 654.68595883],
[ 47.39519707, 666.28232866],
[ 58.07767155, 673.9572227 ],
[ 72.11393347, 683.68307373],
[ 53.70872932, 694.65509894],
[ 82.08237952, 704.5868817 ],
[ 46.64069738, 715.18427515],
[ 40.46032478, 723.91308011],
[ 75.69090892, 733.69595658],
[120.61447884, 745.31322786],
[ 60.17764744, 754.89747186],
[ 87.15961973, 766.24040447],
[ 82.93872713, 773.01518252],
[ 93.56688906, 785.60640153],
[ 70.0474047 , 793.81792947],
[104.3613818 , 805.40234676],
[108.39253837, 814.75002114],
[ 78.97643673, 824.95386427],
[ 85.69096895, 834.44797862],
[ 53.07112931, 844.39555058],
[111.49875807, 855.660508 ],
[ 70.88824958, 865.53417489],
[ 79.55499469, 875.31303945],
[ 60.86941464, 885.85235946],
[101.06017712, 896.69986636],
[ 74.55823544, 905.87417231],
[113.24705653, 915.19350121],
[ 94.21920882, 925.87933273],
[ 63.26478103, 933.70804578],
[ 95.97827181, 945.76196917],
[ 80.48623318, 955.60422694],
[ 80.03451808, 964.39856485],
[ 73.86032436, 973.91032818],
[103.96923524, 984.24366761],
[ 93.20663129, 995.44618851]])
I am trying to combine both, so for each combination of theta_array I get all combinations from XY_array.
I am aware about this post so I have done this:
np.array(np.meshgrid(theta_array, XY_array)).T.reshape(-1,4)
But this generates:
array([[ 1. , 44.0394952 , 1. , 505.81099922],
[ 1. , 61.03882938, 1. , 515.97253226],
[ 1. , 26.69851841, 1. , 525.18083012],
...,
[ 14. , 73.86032436, 14. , 973.91032818],
[ 14. , 103.96923524, 14. , 984.24366761],
[ 14. , 93.20663129, 14. , 995.44618851]])
and the problem requires:
array([[ 1. , 1. , 44.0394952 , 505.81099922],
[ 1. , 1. , 61.03882938, 515.97253226],
[ 1. , 1. , 26.69851841, 525.18083012],
...,
[ 14. , 14. , 73.86032436, 973.91032818],
[ 14. , 14. , 103.96923524, 984.24366761],
[ 14. , 14. , 93.20663129, 995.44618851]])
Which would be the way of doing this combination/aggregation in numpy?
EDIT:
There is a mistake in the above process as the combined arrays do not lead to the generation of that matrix. With separate vectors for each column the actual solution to merge this is:
dataset = np.array(np.meshgrid(theta0_range, theta1_range, X)).T.reshape(-1,3)
And later the Y vector can be added as an additional column.
You can reorder the "columns" after using meshgrid with [:,[0,2,1,3]] and if you need to make the list dynamic because of a large number of columns, then you can see the end of my answer:
np.array(np.meshgrid(theta_array, XY_array)).T.reshape(-1,4)[:,[0,2,1,3]]
Output:
array([[ 1. , 1. , 44.0394952 , 505.81099922]],
[[ 1. , 1. , 61.03882938, 515.97253226]],
[[ 1. , 1. , 26.69851841, 525.18083012]],
...,
[[ 14. , 14. , 73.86032436, 973.91032818]],
[[ 14. , 14. , 103.96923524, 984.24366761]],
[[ 14. , 14. , 93.20663129, 995.44618851]])
If you have many columns you could dynamically create this list: [0,2,1,3] with list comprehension. For example:
n = new_arr.shape[1]*2
lst = [x for x in range(n) if x % 2 == 0]
[lst.append(z) for z in [y for y in range(n) if y % 2 == 1]]
lst
[0, 2, 4, 6, 1, 3, 5, 7]
Then, you could rewrite to:
np.array(np.meshgrid(theta_array, XY_array)).T.reshape(-1,4)[:,lst]
You can use itertools.product:
out = np.array([*product(theta_array, XY_array)])
out = out.reshape(out.shape[0],-1)
Output:
array([[ 1. , 10. , 44.0394952 , 505.81099922],
[ 1. , 10. , 61.03882938, 515.97253226],
[ 1. , 10. , 26.69851841, 525.18083012],
...,
[ 4. , 14. , 73.86032436, 973.91032818],
[ 4. , 14. , 103.96923524, 984.24366761],
[ 4. , 14. , 93.20663129, 995.44618851]])
That said, this looks very much like an XY-problem. What are you trying to do with this array?
Just as side/complementary reference here is a comparison in terms of execution time for both solutions. For this specific operation itertools takes 10 times more time to complete than its numpy equivalent.
%%time
for i in range(1000):
z = np.array(np.meshgrid(theta_array, XY_array)).T.reshape(-1,4)[:,[0,2,1,3]]
CPU times: user 299 ms, sys: 0 ns, total: 299 ms
Wall time: 328 ms
%%time
for i in range(1000):
z = np.array([*product(theta_array, XY_array)])
z = z.reshape(z.shape[0],-1)
CPU times: user 2.79 s, sys: 474 µs, total: 2.79 s
Wall time: 2.84 s

For what reason makes numpy MGrid some indexing convention by complex numbers?

I have some problem with understanding. I read the following:
class MGridClass(nd_grid):
"""
`nd_grid` instance which returns a dense multi-dimensional "meshgrid".
An instance of `numpy.lib.index_tricks.nd_grid` which returns an dense
(or fleshed out) mesh-grid when indexed, so that each returned argument
has the same shape. The dimensions and number of the output arrays are
equal to the number of indexing dimensions. If the step length is not a
complex number, then the stop is not inclusive.
However, if the step length is a **complex number** (e.g. 5j), then
the integer part of its magnitude is interpreted as specifying the
number of points to create between the start and stop values, where
the stop value **is inclusive**.
So if I give real numbers, the content is 'modulo n==0'-wise divided:
>>> numpy.mgrid[0:4:1, 10:15:2]
array([[[ 0, 0, 0],
[ 1, 1, 1],
[ 2, 2, 2],
[ 3, 3, 3]],
[[10, 12, 14],
[10, 12, 14],
[10, 12, 14],
[10, 12, 14]]])
And with complex numbers - the number the integer with j suffix, instead of i for technical purposes - its the length of resulting values in the corresponding axis.
>>> numpy.mgrid[0:4:3j, 10:15:5j]
array([[[ 0. , 0. , 0. , 0. , 0. ],
[ 2. , 2. , 2. , 2. , 2. ],
[ 4. , 4. , 4. , 4. , 4. ]],
[[10. , 11.25, 12.5 , 13.75, 15. ],
[10. , 11.25, 12.5 , 13.75, 15. ],
[10. , 11.25, 12.5 , 13.75, 15. ]]])
But what's special with complex numbers, that they would be appropriate to reflect this change of perspective instead of a simple flag? Is here another part of real fancyness of numpy?

Python - add 1D-array as column of 2D

I want to add a vector as the first column of my 2D array which looks like :
[[ 1. 0. 0. nan]
[ 4. 4. 9.97 1. ]
[ 4. 4. 27.94 1. ]
[ 2. 1. 4.17 1. ]
[ 3. 2. 38.22 1. ]
[ 4. 4. 31.83 1. ]
[ 3. 4. 41.87 1. ]
[ 2. 1. 18.33 1. ]
[ 4. 4. 33.96 1. ]
[ 2. 1. 5.65 1. ]
[ 3. 3. 40.74 1. ]
[ 2. 1. 10.04 1. ]
[ 2. 2. 53.15 1. ]]
I want to add an aray [] of 13 elements as the first column of the matrix. I tried with np.stack_column, np.append but it is for 1D vector or doesn't work because I can't chose axis=1 and only do np.append(peak_values, results)
I have a very simple option for you using numpy -
x = np.array( [[ 3.9427767, -4.297677 ],
[ 3.9427767, -4.297677 ],
[ 3.9427767, -4.297677 ],
[ 3.9427767, -4.297677 ],
[ 3.942777 , -4.297677 ],
[ 3.9427767, -4.297677 ],
[ 3.9427767, -4.297677 ],
[ 3.9427767 ,-4.297677 ],
[ 3.9427767, -4.297677 ],
[ 3.9427772 ,-4.297677 ]])
b = np.arange(10).reshape(-1,1)
np.concatenate((b.T, x), axis=1)
Output-
array([[ 0. , 3.9427767, -4.297677 ],
[ 1. , 3.9427767, -4.297677 ],
[ 2. , 3.9427767, -4.297677 ],
[ 3. , 3.9427767, -4.297677 ],
[ 4. , 3.942777 , -4.297677 ],
[ 5. , 3.9427767, -4.297677 ],
[ 6. , 3.9427767, -4.297677 ],
[ 7. , 3.9427767, -4.297677 ],
[ 8. , 3.9427767, -4.297677 ],
[ 9. , 3.9427772, -4.297677 ]])
Improving on this answer by removing the unnecessary transposition, you can indeed use reshape(-1, 1) to transform the 1d array you'd like to prepend along axis 1 to the 2d array to a 2d array with a single column. At this point, the arrays only differ in shape along the second axis and np.concatenate accepts the arguments:
>>> import numpy as np
>>> a = np.arange(12).reshape(3, 4)
>>> b = np.arange(3)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> b
array([0, 1, 2])
>>> b.reshape(-1, 1) # preview the reshaping...
array([[0],
[1],
[2]])
>>> np.concatenate((b.reshape(-1, 1), a), axis=1)
array([[ 0, 0, 1, 2, 3],
[ 1, 4, 5, 6, 7],
[ 2, 8, 9, 10, 11]])
For the simplest answer, you probably don't even need numpy.
Try the following:
new_array = []
new_array.append(your_array)
That's it.
I would suggest using Numpy. It will allow you to easily do what you want.
Here is an example of squaring the entire set. you can use something like nums[0].
nums = [0, 1, 2, 3, 4]
even_squares = [x ** 2 for x in nums if x % 2 == 0]
print even_squares # Prints "[0, 4, 16]"

Prepending 1d array onto each 2d array of a 3d array

Say I have the size (2,3,2) array a and the size (2) array b below.
import numpy as np
a = np.array([[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]])
b = np.array([0.2, 0.8])
Array a looks like this:
I'd like to use numpy routines to concatenate b to the first row of each 2d arrray in a to make the array
I can't seem to make concatenate, vstack, append, etc. work.
Try this:
np.concatenate(([[b]]*2,a),axis=1)
# Result:
array([[[ 0.2, 0.8],
[ 1. , 2. ],
[ 3. , 4. ],
[ 5. , 6. ]],
[[ 0.2, 0.8],
[ 7. , 8. ],
[ 9. , 10. ],
[ 11. , 12. ]]])
This works:
np.insert(a.astype(float), 0, b, 1)
Output:
array([[[ 0.2, 0.8],
[ 1. , 2. ],
[ 3. , 4. ],
[ 5. , 6. ]],
[[ 0.2, 0.8],
[ 7. , 8. ],
[ 9. , 10. ],
[ 11. , 12. ]]])
If you don't cast with astype() first, you just end up prepending [0, 0]
Note, this is slower than the concatenate():
$ python test.py
m1: 8.20246601105 sec
m2: 43.8010189533 sec
Code:
#!/usr/bin/python
import numpy as np
import timeit
a = np.array([[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]])
b = np.array([0.2, 0.8])
def m1():
np.concatenate(([[b]]*2,a),axis=1)
def m2():
np.insert(a.astype(float), 0, b, 1)
print "m1: %s sec" % timeit.timeit(m1)
print "m2: %s sec" % timeit.timeit(m2)

Categories