Inconsistent Numpy array aliasing behavior - python

The following behavior is expected and is what I get. This is consistent with how aliasing works for native Python objects like lists.
>>> x = np.array([1, 2, 3])
>>> y = x
>>> x
array([1, 2, 3])
>>> y
array([1, 2, 3])
>>> x = x + np.array([2, 3, 4])
>>> x
array([3, 5, 7])
>>> y
array([1, 2, 3])
But the following behavior is unexpected by changing x = x + np.array([2, 3, 4]) to x += np.array([2, 3, 4])
>>> x += np.array([2, 3, 4])
>>> x
array([3, 5, 7])
>>> y
array([3, 5, 7])
The Numpy version is 1.16.4 on my machine. Is this a bug or feature? If it is a feature how x = x + np.array([2, 3, 4]) differs from x += np.array([2, 3, 4])

Your line y = x doesn't create a copy of the array; it simply tells y to point to the same data as x, which you can see if you look at their ids:
x = np.array([1,2,3])
y = x
print(id(x), id(y))
(140644627505280, 140644627505280)
x = x + np.array([2, 3, 4]) will do a reassignment of x to a new id, while x += np.array([2, 3, 4]) will modify it in place. Thus, the += will also modify y, while x = x + ... won't.
x += np.array([2, 3, 4])
print(id(x))
print(x, y)
x = x + np.array([2, 3, 4])
print(id(x))
print(x, y)
140644627505280
[3 5 7] [3 5 7]
140644627175744
[ 5 8 11] [3 5 7]

Related

How to compare two arrarys and create new array with multiple conditional statement?

I have a two arrays x and y with same dimensions. I want to do multiple comparisons (or operator) values in these arrays and generate a new array with same dimensions. The new array should have the values assigned by me. Here is the little demonstration of what I am trying to do:-
In [1]: import numpy
In [2]: import numpy as np
In [3]: x = np.array([5, 2, 3, 1, 4, 5])
In [4]: y = np.array([2, 3, 3, 8, 8, 6])
In [5]: result_array = [y > 3] or [x < 5]
In [6]: print(result_array)
[array([False, False, False, True, True, True], dtype=bool)]
I am able to compare multiple statement and result in new array. However, I would like to replace the True with value 10. So when I try this line, it gives me an error:-
result_array = 10 if [y > 3] or [x < 5]:
File "<ipython-input-21-780bf095bc56>", line 1
result_array = 10 if [y > 3] or [x < 5]:
^
SyntaxError: invalid syntax
What I am expecting is:-
[array([False, False, False, 10, 10, 10], dtype=bool)]
Any help is appreciated
You need to convert your result to integer in order to see the 1:
x = np.array([5, 2, 3, 1, 4, 5])
y = np.array([2, 3, 3, 8, 8, 6])
result_array = np.logical_or(y > 3, x < 5)
res = result_array.astype(int)
res[result_array] = 10
print(res)
Output:
[ 0 10 10 10 10 10]
You can get close to the result you mentioned to be expecting using this:
import numpy as np
x = np.array([5, 2, 3, 1, 4, 5])
y = np.array([2, 3, 3, 8, 8, 6])
result_array = np.where(y > 3, 10, False)
print(result_array)
Result:
[ 0 0 0 10 10 10]
Note that there are 0s instead of Falses, because it contains only numbers

Appending arrays with NumPy

Using NumPy, I want to create an n-by-2 array, by starting with an empty array, and adding on some 1-by-2 arrays.
Here's what I have tried so far:
x = np.array([1, 2])
y = np.array([3, 4])
z = np.array([])
z = np.append(z, x)
z = np.append(z, y)
However, this gives me:
z = [1, 2, 3, 4]
What I want is:
z = [[1, 2], [3, 4]]
How can I achieve this?
import numpy as np
x = np.array([1, 2])
y = np.array([3, 4])
z = np.append([x],[y], axis=0)
print(z)
>>> [[1 2]
[3 4]]
No need to create the array before appending, axis=0 will allow you to append row wise.
The previous works if z is not an array already. From then on you specify z as the original array and append the other array as such:
t = np.array([5, 6])
z = np.append(z,[t], axis=0)
print(z)
[[1 2]
[3 4]
[5 6]]
You can simply use np.array :
>>> np.array((x,y))
array([[1, 2],
[3, 4]])

Condition on numpy arrays

I have two arrays with the same number of elements
X = [1,2,3,4,5,6,7,8,9]
Y = [10,4,3,7,7,3,1,8,98]
I would like to keep the elements of X and Y such as 2<X<7. How can I do?
Ok it works well with
Y = Y[np.logical_and(X>2, X<5)]
X = X[np.logical_and(X>2, X<5)]
Thanks a lot!
You can use numpy.logical_and:
>>> X = np.array([1,2,3,4,5,6,7,8,9])
>>> X[np.logical_and(X>2, X<7)]
array([3, 4, 5, 6])
you can use a loop and if ,and also you can use set() for keep the deferent indexes :
>>> X = [1,2,3,4,5,6,7,8,9]
>>> Y = [10,4,3,7,7,3,1,8,98]
>>> X=[i for i in X if 2<i<7]
>>> Y=[i for i in Y if 2<i<7]
>>> X
[3, 4, 5, 6]
>>> Y
[4, 3, 3]
>>> set(Y)
set([3, 4])

Python lists Ids

Why is the id is of x changes in the following code while it still has the same value. I expect the id for x and z should be same in this case as the value remains the same at the end.
>>> x = [1, 2, 3]
>>> z = x
>>> id(z) == id(x)
True
>>> x = [1, 2, 3]
>>> id(z) == id(x)
False
>>> x
[1, 2, 3]
>>> z
[1, 2, 3]
>>>
What an object holds has nothing to do with its identity. id(x) == id(y) if and only if x and y both refer to the same object.
Maybe this example helps:
x = [1, 2, 3]
y = [1, 2, 3]
z = y
print x, y, z
y[0] = 1000
print x, y, z
which prints this:
[1, 2, 3] [1, 2, 3] [1, 2, 3]
[1, 2, 3] [1000, 2, 3] [1000, 2, 3]
y and z both refer to the same object, so modifying one variable modifies the value retrieved by the other, too. x remains the same because it's a separate object.
What you shouldn't forget is that initializing a variable with a literal list (like [1, 2, 3]) creates a new list object.
Whether or not the two lists contain the same elements does not imply that they should have the same id.
Two variables only have the same id if they refer to the same object, which the second z and x do not:
>>> x = [1, 2, 3]
>>> z = [1, 2, 3]
>>> x[0] = 999
>>> x
[999, 2, 3]
>>> z
[1, 2, 3]
This demonstrates that x and z are two distinct, unrelated lists.

How do i compute with (numpy) -arrays eloquently in python

How can i express this construct in a more efficient way?
x = [2, 4, 6, 8, 10]
for p in x:
x = x/2
print x
there has to be a good way to do this.
If you are trying to divide every element of x by 2, then the following will do it:
x = np.array([2, 4, 6, 8, 10])
x /= 2
The resulting value of x is array([1, 2, 3, 4, 5]).
Note that the above uses integer (truncating) division. If you want floating-point division, either make x into a floating-point array:
x = np.array([2, 4, 6, 8, 10], dtype='float64')
or change the division to:
x = x / 2.0
If it is a numpy array You can do it all at once:
In [4]: from numpy import array
In [5]: x = array([2, 4, 6, 8, 10])
In [6]: print x/2
[1 2 3 4 5]

Categories