Adding elements to numpy array - python

Using NumPy:
X= numpy.zeros(shape=[1, 4], dtype=np.int)
How can I add a list, such as [1,2,3,4]? I tried numpy.add(X,[1,2,3,4]) and np.hstack((1,2,3,4)) but none of them work!
I know how to use that in standard Python list using append method but I want to use numpy for performance.

Numpy arrays don't change shape after they are created. So after invoking method zeros((1,4), ...), you already have a 1x4 matrix full of zeroes. To set its elements to values other than zeroes, you need to use the assignment operator:
X[0] = [1, 2, 3, 4] # does what you are trying to achieve in your question
X[0, :] = [1, 2, 3, 4] # equivalent to the above
X[:] = [1, 2, 3, 4] # same
X[0, 1] = 2 # set the individual element at [0, 1] to 2

Related

Add 1 to numpy array from a list of indices? [duplicate]

This question already has answers here:
Increment Numpy array with repeated indices
(3 answers)
Closed 1 year ago.
I have a numpy array-like
x = np.zeros(4, dtype=np.int)
And I have a list of indices like [1, 2, 3, 2, 1] and I want to add 1 to the corresponding array elements, such that for each element in the index list, x is incremented at that position:
x = [0, 2, 2, 1]
I tried doing this using:
x[indices] += 1
But for some reason, it only updates the indices once, and if an index occurs more often than once it is not registered. I could of course just create a simple for loop but I was wondering if there is a one-line solution.
What you are essentially trying to do, is to replace the indexes by their frequencies.
Try np.bincount. Technically that does the same what you are trying to do.
indices = [1, 2, 3, 2, 1]
np.bincount(indices)
array([0, 2, 2, 1])
If you think about what you are doing. You are saying that for index 0, you dont want to count anything. but for index 1, you want 2 counts, .. and so on. Hope that gives you an intuitive sense of why this is the same.
#Stef's solution with np.unique, does exactly the same thing as what np.bincount would do.
You can use unique with return_counts set to True:
idx, cnt = np.unique(indices, return_counts=True)
x[idx] += cnt
You want np.add.at:
np.add.at(x, indices, 1)
x
Out[]:
array([0, 2, 2, 1])
This works even if x doesn't start out as np.zeros
Based on your question, you can really just write
import numpy as np
indices = [1, 2, 3, 2, 1]
x = np.array([indices.count(i) for i in range(4)])
Because count counts repeated elements. But the full solution would be
import numpy as np
x = np.zeros(4, dtype=np.int)
indices = [1, 2, 3, 2, 1]
result = np.array([indices.count(i) for i in range(4)])
x += result

Check if any row in a numpy array is part of another array [duplicate]

This question already has an answer here:
Check if two 3D numpy arrays contain overlapping 2D arrays
(1 answer)
Closed 2 years ago.
I'm using numpy for the first time. I am trying to achieve the following:
There are 2 arrays:
a = np.array([[1, 3], [2, 5], [1, 2], [2, 1], [1,6]])
b = np.array([[3, 5], [1, 2]])
I need to check if ANY pair (or a row in other words) in array b is present in array a, in the same order (as in, [1, 2] is not to be considered same as [2, 1])
The above example should return True since both a and b contain [1, 2]
I've tried:
for [x, y] in b
if [x, y] in a
and:
if (a == b).all(1).any() # --> This throws "AttributeError: 'bool' object has no attribute 'all'"
but failed.
Thanks in advance
Let do it the numpyic way (loops are not advised with numpy). Add a dimension using None to let the numpy do the correct broadcasting, then use any and all along correct axis:
(a==b[:,None]).all(-1).any()
Output for sample input in question:
True
This solution use np.ravel_multi_index to avoid broadcasting. If your array is big, this is helpful since it doesn't use broadcasting
d = np.maximum(a.max(0), b.max(0))+1
np.in1d(np.ravel_multi_index(a.T,d), np.ravel_multi_index(b.T,d)).any()
Out[71]: True
This solution is also able to give position of the row in a where it matches
np.nonzero(np.in1d(np.ravel_multi_index(a.T,d), np.ravel_multi_index(b.T,d)))[0]
Out[72]: array([2], dtype=int64)
Note: I learned this trick a long time ago from #Divakar . so, credit should go to him.
Try:
a = np.array([[1, 3], [2, 5], [1, 2], [2, 1], [1,6]])
b = np.array([[3, 5], [1, 2]])
check = any(map(lambda x: x in b, a))
Explanation:
lambda is a key word to create a function. In this case:
lambda x: x in b
it represents a function that takes an x and returns if x is in array b
map is a built-in function that takes a function as a first argument, and an iterable as a second argument.
what it does is apply the first argument (the function) to every item in the iterable (the second argument) and return an iterable with these values.
In this case:
map(lambda x: x in b, a)
it returns an iterable of True and False depending the result of applying the function throw the elements.
Finally, any its another build-in function that takes and iterable of True's and False's and returns True if any item on the iterable is True
EDIT:
You can also do it using list comprehension (as someone write it down in comments):
a = np.array([[1, 3], [2, 5], [1, 2], [2, 1], [1,6]])
b = np.array([[3, 5], [1, 2]])
check = any(x in b for x in a)
It is exactly the same and even more legible.

Retrieve column slices from a NumPy array using variables as the indexer

Say I have an array and I want a function to select some of its columns based on an argument a that is pre-defined :
extracted_columns = array[:,a].
If I have e.g. a = np.arange(10), I'll get the first ten columns,
What if I want to define a so that all the columns are selected without knowing the size of the array ?
I'd like to set a = : so that the function does
extracted_columns = array[:,:]
but it seems : can't pas passed as an argument. I also tried a = None but this gives me an array of dimensions 3 with the second dimension equal to 1.
Is there a nice way of doing it ?
Thanks,
Pass a slice object to your function.
MCVE:
x = np.arange(9).reshape(3, 3)
print(x)
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
a = slice(None)
print(x[:, a])
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
For your case, you'd define a function along these lines:
def foo(array, a):
return array[:, a]
And call it like this:
arr_slice = foo(array, slice(None))

How can I use the unique(a, 'rows') from MATLAB in Python?

I'm translating some stuff from MATLAB to the Python language.
There's this command, unique(a), in NumPy. But since the MATLAB program runs the 'rows' command also, it gives something a little different.
Is there a similar command in Python or should I make some algorithm that does the same thing?
Assuming your 2D array is stored in the usual C order (that is, each row is counted as an array or list within the main array; in other words, row-major order), or that you transpose the array beforehand otherwise, you could do something like...
>>> import numpy as np
>>> a = np.array([[1, 2, 3], [2, 3, 4], [1, 2, 3], [3, 4, 5]])
>>> a
array([[1, 2, 3],
[2, 3, 4],
[1, 2, 3],
[3, 4, 5]])
>>> np.array([np.array(x) for x in set(tuple(x) for x in a)]) # or "list(x) for x in set[...]"
array([[3, 4, 5],
[2, 3, 4],
[1, 2, 3]])
Of course, this doesn't really work if you need the unique rows in their original order.
By the way, to emulate something like unique(a, 'columns'), you'd just transpose the original array, do the step shown above, and then transpose back.
You can try:
ii = 0; wrk_arr = your_arr
idx = numpy.arange(0,len(wrk_arr))
while ii<=len(wrk_arr)-1:
i_list = numpy.arange(0,len(wrk_arr)
candidate = numpy.matrix(wrk_arr[ii,:])
i_dup = numpy.array([0] * len(wrk_arr))
numpy.all(candidate == wrk_arr,axis=1, iout = idup)
idup[ii]=0
i_list = numpy.unique(i_list * (1-idup))
idx = numpy.unique(idx * (1-idup))
wrk_arr = wrk_arr[i_list,:]
ii += 1
The results are wrk_arr which is the unique sorted array of your_arr. The relation is:
your_arr[idx,:] = wrk_arr
It works like MATLAB in the sense that the returned array (wrk_arr) keeps the order of the original array (your_arr). The idx array differs from MATLAB since it contains the indices of first appearance whereas MATLAB returns the LAST appearance.
From my experience it worked as fast as MATLAB on a 10000 X 4 matrix.
And a transpose will do the trick for the column case.

How to make a copy of a 2D array in Python? [duplicate]

This question already has answers here:
Copying nested lists in Python
(3 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 4 years ago.
X is a 2D array. I want to have a new variable Y that which has the same value as the array X. Moreover, any further manipulations with Y should not influence the value of the X.
It seems to me so natural to use y = x. But it does not work with arrays. If I do it this way and then changes y, the x will be changed too. I found out that the problem can be solved like that: y = x[:]
But it does not work with 2D array. For example:
x = [[1,2],[3,4]]
y = x[:]
y[0][0]= 1000
print x
returns [ [1000, 2], [3, 4] ]. It also does not help if I replace y=x[:] by y = x[:][:].
Does anybody know what is a proper and simple way to do it?
Using deepcopy() or copy() is a good solution.
For a simple 2D-array case
y = [row[:] for row in x]
Try this:
from copy import copy, deepcopy
y = deepcopy(x)
I'm not sure, maybe copy() is sufficient.
For 2D arrays it's possible use map function:
old_array = [[2, 3], [4, 5]]
# python2.*
new_array = map(list, old_array)
# python3.*
new_array = list(map(list, old_array))
In your case(since you use list of lists) you have to use deepcopy, because 'The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.'
Note that sample below is simply intended to show you an example(don't beat me to much) how deepcopy could be implemented for 1d and 2d arrays:
arr = [[1,2],[3,4]]
deepcopy1d2d = lambda lVals: [x if not isinstance(x, list) else x[:] for x in lVals]
dst = deepcopy1d2d(arr)
dst[1][1]=150
print dst
print arr
I think np.tile also might be useful
>>> a = np.array([0, 1, 2])
>>> np.tile(a, 2)
array([0, 1, 2, 0, 1, 2])
>>> np.tile(a, (2, 2))
array([[0, 1, 2, 0, 1, 2],
[0, 1, 2, 0, 1, 2]])
>>> np.tile(a, (2, 1, 2))
array([[[0, 1, 2, 0, 1, 2]],
[[0, 1, 2, 0, 1, 2]]])

Categories

Resources