Is there any operation on two numpy array to discard zero values? - python

Suppose we have two numpy array x1 and x2 like below:
x1 = np.array([[0,2,9,1,0]])
x2 = np.array([[7,3,0,6,8]])
Is there any operation like:
x2(operation)x1 = array([[ 0, 3, 0, 6, 0]])
i.e. if x1 or x2 is 0 at any index then make the result array's index value as zero. Otherwise, keep x2 as it is.

Use numpy.where:
x3 = np.where(x1 == 0, x1, x2)
print(x3)
Output:
[[0 3 0 6 0]]

Given that you want to keep x2 but make it zero in the case x1 is zero, just multiply x2 by the boolean of x1.
>>> x2 * x1.astype(bool)
array([[0, 3, 0, 6, 0]])
Note that if x2 is zero, the result is zero as expected.

Related

Python. Recursive matrix product with result as a set of vectors

As an application of Eulers method, I'm trying to implement a code which would compute the recursive matrix product Yn = Yn-1 + A(Yn-1), where Y is a vector and A is a matrix such that the product is defined. This is the current code I have
def f(A, y):
return A.dot(y)
def euler(f, t0, y0, T, dt):
t = np.arange(t0, T + dt, dt)
y = [0,0,0,0]*len(t)
y[0] = y0
for i in range(1, len(t)):
y[i] = y[i - 1] + f(A, y[i - 1])*dt
return t, y
# Define problem specific values
A = np.array([[0, 0, 1, 0],
[0, 0, 0, 1],
[-2, -3, 0, 0],
[-3, -2, 0, 0]])
y1_0 = 1
y2_0 = 2
y3_0 = 0
y4_0 = 0
y0 = [y1_0, y2_0, y3_0, y4_0]
t,y = euler(f,0,y0,2,1)
print(t,y)
For example, the result for points in the range t0 = 0, T = 2 should be the vectors Y1 and Y2. Instead I have
[0 1 2] [[1, 2, 0, 0], array([ 1, 2, -8, -7]), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Something is wrong here. While Y1 = [1, 2, -8, -7 ] does show up, there is all of this unnecessary stuff. And Y2 is not printed at all. I suspect this is due to how I define the variable y. For every point in the range of t, I need a vector of 4 zeros - which is then filled up by the function euler, I think. How should correct this?
The computer always does what you tell it to do. In your case y is constructed by repeating 4 zeros len(t) times, giving a list of 12 zeros. The first list entry is replaced by the list y0. The second list entry is replaced by the result of the numpy operations which is a numpy.array. Then the return statement at the level of the loop instructions breaks the loop and returns the t and y arrays. y still contains 10 zeros from its construction that were not replaced.
So construct
y = np.zeros([len(t), len(y0)])
and repair the indentation level.

How to update a Tensor?

I've had some troubles updating a tensor using a previous one.
My problem: let's suppose that I have a tensor x1 [Nx1] and a new one calculated through the previous, x2 [Nx1]. Now I want to update the elements of x2 that are less than x1. I'm using dtype=torch.cuda.FloatTensor.
This is the straight code in Python:
import numpy as np
...
index = np.where(x1 > x2)
x2[index] = x1[index]
Why can I do this using PyTorch with dtype=torch.cuda.FloatTensor?
And if the x1 change to [NxD]
Thank you!
The code looks really similar to numpy:
idx = (x1 > x2)
x2[idx] = x1[idx]
Using some predefined arrays and printing x2:
x1 = torch.from_numpy(np.array([1, 2, 3, 4, 5])).float().cuda()
x2 = torch.from_numpy(np.array([3, 3, 3, 3, 3])).float().cuda()
3 3 3 4 5
[torch.cuda.FloatTensor of size 5 (GPU 0)]
Code would be the same for NxN dimensional tensors. Using:
x1 = torch.from_numpy(np.array([[1, 2, 5], [1, 4, 5]])).float().cuda()
x2 = torch.from_numpy(np.array([[3, 3, 3], [3, 3, 3]])).float().cuda()
3 3 5
3 4 5
[torch.cuda.FloatTensor of size 2x3 (GPU 0)]

Linear programming, unexpected solution with equality constraint

I'm trying to figure out what is wrong with my implementation, I expect the result to be [5, 10], I don't understand how it gets [7.5, 7.5], x1 should be half of x2.
from scipy.optimize import linprog
import numpy as np
c = [-1, -1]
A_eq = np.array([
[1, 0.5],
[1, -0.5],
])
b_eq = [15, 0]
x0_bounds = (0, None)
x1_bounds = (0, None)
res = linprog(
c,
A_eq=A_eq.transpose(),
b_eq=b_eq,
bounds=(x0_bounds, x1_bounds),
options={"disp": True})
print res.x
# =>
# Optimization terminated successfully.
# Current function value: -15.000000
# Iterations: 2
# [ 7.5 7.5]
Update from the author:
As it was said matrix transposition is not needed here.
The problem was in the matrix itself, in order to get desired result, which is [5, 10], it has to be:
A_eq = np.array([
[1, 1],
[1, -0.5],
])
Per the scipy linprog docs:
Minimize: c^T * x
Subject to:
A_ub * x <= b_ub
A_eq * x == b_eq
So, you are now solving the following equations:
Minimize -x1 -x2
Subject to,*
x1 + x2 = 15 (i)
0.5 * x1 - 0.5 * x2 = 0 (ii)
Now, (ii) implies x1 = x2 (so your desired solution is infeasable), and then (i) fixes x1 = x2 = 7.5. So, the solution returned by linprog() is indeed correct. Since you are expecting a different result, maybe you should look into the way you translated your problem into code, as I think that's where you will find both the issue and the solution.
*) Since you are taking the transpose.
Your problem is:
x1 + x2 == 15
0.5 * x1 - 0.5 * x2 == 0
minimize -x1 -x2
So obviously you have x1 == x2 (second constraint), and thus x1 = x2 = 7.5 (first constraint).
Looking at your question, you probably don't want to transpose A:
res = linprog(
c,
A_eq=A_eq,
b_eq=b_eq,
bounds=(x0_bounds, x1_bounds),
options={"disp": True}
)
Why gives you the problem:
x1 + 0.5 * x2 == 15
x1 - 0.5 * x2 == 0
minimize -x1 -x2
And you get x1 = 7.5 and x2 = 15 (the only possible values).

Pythonic way to select elements of an array based on values?

I'm looking for a pythonic (1-line) way to extract a range of values from an array
Here's some sample code that will extract the array elements that are >2 and <8 from x,y data, and put them into a new array. Is there a way to accomplish this on a single line? The code below works but seems kludgier than it needs to be. (Note I'm actually working with floats in my application)
import numpy as np
x0 = np.array([0,3,9,8,3,4,5])
y0 = np.array([2,3,5,7,8,1,0])
x1 = x0[x0>2]
y1 = y0[x0>2]
x2 = x1[x1<8]
y2 = y1[x1<8]
print x2, y2
This prints
[3 3 4 5] [3 8 1 0]
Part (b) of the problem would be to extract values say 1 < x < 3 and 7 < x < 9 as well as their corresponding y values.
You can chain together boolean arrays using & for element-wise logical and and | for element-wise logical or, so that the condition 2 < x0 and x0 < 8 becomes
mask = (2 < x0) & (x0 < 8)
For example,
import numpy as np
x0 = np.array([0,3,9,8,3,4,5])
y0 = np.array([2,3,5,7,8,1,0])
mask = (2 < x0) & (x0 < 8)
x2 = x0[mask]
y2 = y0[mask]
print(x2, y2)
# (array([3, 3, 4, 5]), array([3, 8, 1, 0]))
mask2 = ((1 < x0) & (x0 < 3)) | ((7 < x0) & (x0 < 9))
x3 = x0[mask2]
y3 = y0[mask2]
print(x3, y3)
# (array([8]), array([7]))
import numpy as np
x0 = np.array([0,3,9,8,3,4,5])
y0 = np.array([2,3,5,7,8,1,0])
list( zip( *[(x,y) for x, y in zip(x0, y0) if 1<=x<=3 or 7<=x<=9] ) )
# [(3, 9, 8, 3), (3, 5, 7, 8)]

Finding specific values and replacing them by others. Python

I am very new to programming. I have code in matlab:
x2(x2>=0)=1;
x2(x2<0)=-1;
%Find values in x2 which are less than 0 and replace them with -1,
%where x2 is an array like
0,000266987932788242
0,000106735120804439
-0,000133516844874253
-0,000534018243439120
I tried to do this in Python using code
if x2>=0:
x2=1
if x2<0:
x2=-1
This returns ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
How should I do it so that I get all the positive replaced by 1 and negatives by -1 and STORE all of this in the x2 for example, not just print, so that I could use it later to do some other stuff.
You can use numpy's ability to index over boolean array.
import numpy as np
x = np.array([-5.3, -0.4, 0.6, 5.4, 0.0])
not_neg = x >= 0 # creates a boolean array
x[not_neg] = 1 # index over boolean array
x[~not_neg] = -1
Result:
>>> x
array([-1., -1., 1., 1., 1.])
First:
x2 = [0.000266987932788242, 0.000106735120804439, -0.000133516844874253, -0.000534018243439120]
print [1 if num >= 0 else num for num in x2]
Output
[1, 1, -0.000133516844874253, -0.000534018243439120]
Second:
x2 = [-1, 2, -3, 4]
print [-1 if num < 0 else num for num in x2]
Output
[0.000266987932788242, 0.000106735120804439, -1, -1]
If you need both of them in a single statement
x2 = [0.000266987932788242, 0.000106735120804439, -0.000133516844874253, -0.000534018243439120]
x2 = [-1 if num < 0 else 1 for num in x2]
print x2
Output
[1, 1, -1, -1]

Categories

Resources