Select values in arrays - python

I have two arrays of the same length:
x = [2,3,6,100,2,3,5,8,100,100,5]
y = [2,3,4,5,5,5,2,1,0,2,4]
I selected the position where x==100 in this way:
How is possible to have the value of y where x==100? (that is y=5,0,2)?
I tried in this way:
x100=np.where(x==100)
y100=y[x100]
but it doesn't give me the values I want. How can I solve the problem?

Your code works fine when actually using numpy arrays. You can also write it more succinctly like so.
>>> import numpy as np
>>> x = np.array([2,3,6,100,2,3,5,8,100,100,5])
>>> y = np.array([2,3,4,5,5,5,2,1,0,2,4])
>>> y[x == 100]
array([5, 0, 2])

x and y should be numpy arrays:
x = np.array([2,3,6,100,2,3,5,8,100,100,5])
y = np.array([2,3,4,5,5,5,2,1,0,2,4])
Then your code should work as you expect.

What about
[b for (a,b) in zip(x,y) if a==100]
or
itertools.compress(y, [a==100 for a in x])

Iterate over both and check for 100:
x = [2,3,6,100,2,3,5,8,100,100,5]
y = [2,3,4,5,5,5,2,1,0,2,4]
for xi, yi in zip(x, y):
if xi == 100:
print(yi)
Prints:
5
0
2
Or as list comprehension:
>>> [yi for xi, yi in zip(x, y) if xi == 100]
[5, 0, 2]

Related

Solve system of 2 integer equations

I have a set of two equations with three unknowns that has some conditions. x, y and z must all be larger than zero. How can I solve this? There is only one solution and I already know it, but I want to know how to get to it correctly.
These are the equations:
100 = x + y + z
100 = 10x +2.5y + 0.5z
Need to find x, y and z. They are integers and positive.
This is the code I have, but that does not work:
from sympy import symbols, Eq, solve
x, y, z = symbols('x y z')
eq1 = Eq(x + y + z, 100)
eq2 = Eq(x*10 + y*2.5 + z*0.5, 100)
#eq3 = x, y, z must all be larger than zero and integers
solution = solve((eq1,eq2), (x,y,z))
solution
In sympy if you want to find integer solutions to equations then you should use diophantine. It doesn't handle systems of equations but you can put the solution from one equation into the other and call diophantine again:
In [69]: eq1 = x + y + z - 100
In [70]: eq2 = 10*x + 5*y/2 + z/2 - 100
In [71]: sol = diophantine(eq1, t, syms=[x, y, z])
In [72]: sol
Out[72]: {(t₀, t₀ + t₁, -2⋅t₀ - t₁ + 100)}
In [73]: [xt, yt, zt], = sol
In [74]: eq3 = eq2.subs({x:xt, y:yt, z:zt})
In [75]: eq3
Out[75]:
23⋅t₀
───── + 2⋅t₁ - 50
2
In [76]: t1, t2 = eq3.free_symbols
In [77]: [t1s, t2s], = diophantine(eq3, z, syms=[t1, t2])
In [78]: rep = {t1:t1s, t2:t2s}
In [79]: (xt.subs(rep), yt.subs(rep), zt.subs(rep))
Out[79]: (4⋅z₀ - 100, 500 - 19⋅z₀, 15⋅z₀ - 300)
The solution here is in terms of an integer parameter z0. This gives the set of solutions to the two equations but you also have the requirement that x, y, z are positive which constrains the possible values of z0:
In [80]: ineqs = [s.subs(rep) > 0 for s in [xt, yt, zt]]
In [81]: ineqs
Out[81]: [4⋅z₀ - 100 > 0, 500 - 19⋅z₀ > 0, 15⋅z₀ - 300 > 0]
In [82]: solve(ineqs)
Out[82]:
500
25 < z₀ ∧ z₀ < ───
19
In [83]: 500/19
Out[83]: 26.31578947368421
We see that z needs to be 26 which gives a unique solution for x, y and z:
In [84]: z, = ineqs[0].free_symbols
In [85]: (xt.subs(rep).subs(z, 26), yt.subs(rep).subs(z, 26), zt.subs(rep).subs(z, 26))
Out[85]: (4, 6, 90)
This type of problem can be solved by Z3py, a SAT/SMT solver:
from z3 import Ints, solve
x, y, z = Ints('x y z')
sol = solve(x + y + z == 100, x * 100 + y * 25 + z * 5 == 1000, x > 0, y > 0, z > 0)
print(sol)
Output: [z = 90, y = 6, x = 4].
Note that in general, Z3 only looks for one solution. To find subsequent solutions, a clause needs to be added to prohibit the already found solutions. (In this case there seems to be only one solution.)
You did not explicitly state it but according to your comment x,y and z should be integers.
This complicates matters a bit.
This is now an example of a mixed integer programming (MIP) problem.
You could take a look at the following package for solving this in python:
mip
The downside of solving MIP's is that they are NP hard. But for this small example this should not matter.

Python list of object extraction into sub list

Say I have a class called 'points' with attributes 'x' and 'y'
and I create a list of points p = [p1,p2,p3,p4]
where p1.x = x1, py.y = y1 ...
How do I easily extract all the x and y values as a list?
e.g.
x = [x1,x2,x3,x4]
y = [y1,y2,y3,y4]
can this be done simply in one line of code in python?
You can do something like this:
p = [p1,p2,p3,p4]
x = [point.x for point in p]
y = [point.y for point in p]
x = [point.x for point in p]
y = [point.y for point in p]
could work but this will iterate the p twice, which is unnecessary ,You could try:
p = [p1, p2, p3, p4]
x, y = list(zip(*[(point.x, point.y) for point in p]))
Here you are
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
points = [Point(1,2), Point(3,4), Point(5,6), Point(7,8)]
x = [p.x for p in points]
y = [p.y for p in points]
print(x)
print(y)
Output :
[1, 3, 5, 7]
[2, 4, 6, 8]
Try it here
You could do it like this
x, y = [point.x for point in p],[point.y for point in p]

Why my function cannot draw by matlibplot

I set a function like that:
def triangular(x, a, b, c):
if x <= a:
return 0
if a < x <= b:
return (x - a)/(b - a)
if b < x <= c:
return (c - x)/(c - b)
if c < x:
return 0
I want to draw the image of this function so I use:
x = range(-10, 10, 0.1)
y = triangular(x,1,2,3)
plt.figure()
plt.plot(x,y)
plt.show()
However, it shows error:'float' object cannot be interpreted as an integer, why? need I correct my function or input?
I tried to change to
x = np.arange(-10, 10, 0.1)
y = triangular(x,1,2,3)
plt.figure()
plt.plot(x,y)
plt.show()
it shows
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Instead of
x = range(-10, 10, 0.1)
y = triangular(x,1,2,3)
use
import numpy as np
...
x = np.arange(-10, 10, 0.1)
y = [triangular(elem_x,1,2,3) for elem_x in x]
You can also use NumPy indexing and masking to approach this problem avoiding for loops. Below is how you can do it. The conditions I am writing inside the function triangular in the square brackets [...] are just the boundary conditions described in your problem. It is more intuitive in the way it is written
def triangular(x, a, b, c):
x[x<=a] = 0
x[(a<x) & (x<=b)] = (x[(a<x) & (x<=b)] - a)/(b - a)
x[(b<x) & (x<=c)] = (c - x[(b<x) & (x<=c)])/(c - b)
x[x>c] = 0
return x
x = np.arange(-10, 10, 0.1)
y = triangular(x.copy(),1,2,3)
plt.figure()
plt.plot(x,y)
plt.show()

numpy iterate over two 2d arrays

Say I have two matrices:
X, Y = np.meshgrid(np.arange(0, 2, 0.1), np.arange(3, 5, 0.1))
And a function, something like:
def func(x) :
return x[0]**2 + x[1]**2
How can I fill a matrix Z (of size np.shape(X)), where each entry is formed by calling func on the two corresponding values of X and Y, i.e.:
Z[i, j] = func([X[i, j], Y[i, j]])
Is there a way without using a double nested for-loop?
This is also works as a vectorized form of function evaluation:
import numpy as np
X, Y = np.meshgrid(np.arange(0, 2, 0.1), np.arange(3, 5, 0.1))
def func(x) :
return x[0]**2 + x[1]**2
Z = func([X,Y])
For given numpy arrays X and Y, you could just do -
Zout = X**2 + Y**2
If you are actually constructing X and Y like that, there is a direct way to get Z with broadcasting and thus avoid np.meshgrid, like so -
Zout = np.arange(0, 2, 0.1)**2 + np.arange(3, 5, 0.1)[:,None]**2

"Properly" organise (spread out) x and y data

Not really sure how to word this question, so I will give an example of what I want.
I have two variables xsteps and ysteps.
If xsteps is 4 and ysteps is 2, then I would like a variable result to be "x, x, y, x, x, y"
If xsteps is 10 and ysteps is 5, then I would like result to be
"x, x, y, x, x, y, x, x, y, x, x, y, x, x, y"
If xsteps is 15 and ysteps is 5 then I would like result to be "x, x, x, y, x, x, x, y, x, x, x, y, x, x, x, y, x, x, x, y"
If xsteps is 1 and ysteps is 6, I would like result to be "x, y, y, y, y, y, y"
If xsteps is 4 and ysteps is 4, I would like result to be "x, y, x, y, x, y, x, y"
If xsteps is 10 and ysteps is 4, I would like result to be "x, x, y, x, x, y, x, x, y, x, x, y, x, x"
Xsteps and ysteps are not always easily divisible. If they do not divide, then I would just like them to be kind of separated out. It does not need to be perfect, just so it spreads them out reasonable well.
Really, I need the xsteps and ysteps variables organised into one variable that spreads them out.
You can try something like this:
from __future__ import division
def spreadout(X, Y):
ratio = len(X) / len(Y)
result = []
while X or Y:
if not Y or len(X)/len(Y) >= ratio:
result.append(X.pop())
else:
result.append(Y.pop())
return result
The idea behind the algorithm is to determine the ratio of the X andY lists and to alternately pop elements from either of the lists to keep the ratio in the result list similar.
This implementaiton works with lists of arbitrary elements and will return the result as a list. If you want just your x,y string, the code can be simplified and optimized some, e.g. using len this often would be wasteful is you have very long lists of xs and ys. Or you can just write a wrapper for that:
def xy_wrapper(x, y):
return ",".join(spreadout(['x'] * x, ['y'] * y))
Example Output:
>>> spreadout(range(6), list("ABC"))
[5, 'C', 4, 3, 'B', 2, 1, 'A', 0]
>>> xy_wrapper(5, 17)
'x,y,y,y,y,x,y,y,y,x,y,y,y,y,x,y,y,y,x,y,y,y'
def spread_generator(xsteps, ysteps):
ratio = xsteps / ysteps
while xsteps > 0 or ysteps > 0:
if xsteps > ratio * ysteps:
yield "x"
xsteps -= 1
else:
yield "y"
ysteps -= 1
xsteps = 7
ysteps = 3
result = [x for x in spread_generator(xsteps, ysteps)]
# Next line will make result variable hold desired value
result.reverse()
print result
# ['x', 'x', 'y', 'x', 'x', 'y', 'x', 'x', 'y', 'x']
# And if you want string
result_as_str = ",".join(result)
print result_as_str
# x,x,y,x,x,y,x,x,y,x
The crucial value is the ratio between x and y steps.
The list is reversed in the beginning, so we reverse it.
Remember that list.reverse() modifies the list in place and returns None.
Looks like someone beat me to the punch with a much nicer response, but I've written it now!
This would do close to what you want, but your example for (10, 4) doesn't work the way you have specified it.
def xy_spread(xsteps, ysteps):
out = []
if xsteps == 0:
out = ['y'] * ysteps
else:
y_per_x = float(ysteps) / float(xsteps)
y_budget = 0.0
for _ in xrange(xsteps):
out.append('x')
y_budget += y_per_x
while y_budget >= 1:
y_budget -= 1
out.append('y')
return ','.join(out)
Not necessarily pretty, but functional.
Basically it seems you want to split the xsteps into chunks, and intersperse a "y" between the chunks until either the x's or y's run out.
def get_chunks(mylist, n):
"""
Adapted from:
http://www.how2code.co.uk/2013/04/how-to-split-a-list-into-chunks-in-python/
"""
if n == 0:
return mylist
else:
return [mylist[x:x+n] for x in range(0, len(mylist), n)]
def combine(xs=0, ys=0):
"""
>>> combine(xs=4, ys=2)
x,x,y,x,x,y
>>> combine(xs=10, ys=5)
x,x,y,x,x,y,x,x,y,x,x,y,x,x,y
>>> combine(xs=15, ys=5)
x,x,x,y,x,x,x,y,x,x,x,y,x,x,x,y,x,x,x,y
>>> combine(xs=1, ys=6)
x,y,y,y,y,y,y
>>> combine(xs=4, ys=4)
x,y,x,y,x,y,x,y
>>> combine(xs=10, ys=4)
x,x,y,x,x,y,x,x,y,x,x,y,x,x
"""
output = list()
x = ['x'] * xs
y = ['y'] * ys
step = xs // ys
xchunks = get_chunks(x, step)
while xchunks or y:
if xchunks:
output += xchunks.pop()
if y:
output += y.pop()
print ','.join(output)

Categories