I have a list of points in the form of
points=[(x1,y1),...(xn,yn)...]
I am looking for a pythonic way to transform the list into
x=[x1,...xn] y=[y1,...yn]
One way to do it would be
x = map (lambda x: x[1],points)
However, maybe there is a more pythonic way to directly draw from "points" mentioned above?
You can do something like this:
x = []
y = []
for point in points:
x.append(point[0])
y.append(point[1])
or:
x,y = [i[0] for i in points], [i[1] for i in points]
but the best way is to use zip:
x,y = zip(*points)
zip is better than map and it is faster, you should define a function in map with lambda. so I think the best way to do this is with zip.
In addition to mehrdad-pedramfar answer:
If using numpy is not a problem you can convert your list of tuples to a numpy array and then just use indexing.
import numpy as np
short_example = np.array([(1,2),(2,4),(4,6)])
short_example[:,0]
gives a numpy array of all x values:
array([1, 2, 4])
short_example[:,1]
gives a numpy array of all y values:
array([2, 4, 6])
Related
I have written this piece of code:
data = np.array([[3,6], [5,9], [4, 8]])
orig_x, orig_y = np.split(data, 2, axis=1)
x = np.array([3, 4])
y = np.zeros((len(x)))
for i in range(len(x)):
y[i] = orig_y[np.where(orig_x == x[i])[0]]
So basically, I have a 2D NumPy array. I split it into two 1D arrays orig_x and orig_y, one storing values of the x-axis and the other values of the y-axis.
I also have another 1D NumPy array, which has some of the values that exist in the orig_x array. I want to find the y-axis values for each value in the x array. I created this method, using a simple loop, but it is extremely slow since I'm using it with thousands of values.
Do you have a better idea? Maybe by using a NumPy function?
Note: Also a better title for this question can be made. Sorry :(
You could create a mask over which values you want from the x column and then use this mask to select values from the y column.
data = np.array([[3,6], [5,9], [4, 8]])
# the values you want to lookup on the x-axis
x = np.array([3, 4])
mask = np.isin(data[:,0], x)
data[mask,1]
Output:
array([6, 8])
The key function here is to use np.isin. What this is basically doing is broadcasting x or data to the appropriate shape and doing an element-wise comparison:
mask = data[:,0,None] == x
y_mask = np.logical_or.reduce(mask, axis=1)
data[y_mask, 1]
Output:
array([6, 8])
I'm not 100% sure I understood the problem correctly, but I think the following should work:
>>> rows, cols = np.where(orig_x == x)
>>> y = orig_y[rows[np.argsort(cols)]].ravel()
>>> y
array([6, 8])
It assumes that all the values in orig_x are unique, but since your code example has the same restriction, I considered it a given.
What about a lookup table?
import numpy as np
data = np.array([[3,6], [5,9], [4, 8]])
orig_x, orig_y = np.split(data, 2, axis=1)
x = np.array([3, 4])
y = np.zeros((len(x)))
You can pack a dict for lookup:
lookup = {i: j for i, j in zip(orig_x.ravel(), orig_y.ravel())}
And just map this into a new array:
np.fromiter(map(lambda i: lookup.get(i, np.nan), x), dtype=int, count=len(x))
array([6, 8])
If orig_x & orig_y are your smaller data structures this will probably be most efficient.
EDIT - It's occurred to me that if your values are integers the default np.nan won't work and you should figure out what value makes sense for your application if you're trying to find a value that isn't in your orig_x array.
I have a three vectors of x,y,z coordinates, something like
x = [1,2,3,4,5]
y = [6,7,8,9,10]
z = [11,12,13,14,15]
I want to zip them to have an 5x3 array of coordinates. But when I do
coords = zip(x,y,z)
and then try to print coords, I get
and I cannot plot them either,
How can I get 5x3 array?
You can use numpy function directly:
np.array(list(zip(x,y,z)))
If you didn't import numpy:
import numpy as np
call list on the zip object or use it in a list comprehension.
I've to map R^2 array X=[x1, x2] into R^3 array X'=[x1, x2, x1^2].
Is there any compact solution?
ADDED: My starting array is a numpy array e.g. x = numpy.array([2, 3]). I want to end up with another numpy array e.g. x' = numpy.array([2, 3, 4]).
For the case where your array is a numpy array with shape (2,), one way to add the additional member is
xx = numpy.append(x, x[0]**2)
Unfortunately, if you try something like x + [x[0]**2] numpy will add the elements together rather than append the new element. If you try something like [x[0], x[1], x[0]**2] you end up with a list rather than a numpy array.
I need to carry out some operation on a subset of an NxN array. I have the center of the sub-array, x and y, and its size.
So I can easily do:
subset = data[y-size:y+size,x-size:x+size]
And this is fine.
What I ask is if there is the possibility to do the same without writing an explicit loop if x and y are both 1D arrays of positions.
Thanks!
Using a simple example of a 5x5 array and setting size=1 we can get:
import numpy as np
data = np.arange(25).reshape((5,5))
size = 1
x = np.array([1,4])
y = np.array([1,4])
subsets = [data[j-size:j+size,i-size:i+size] for i in x for j in y]
print(subsets)
Which returns a list of numpy arrays:
[array([[0, 1],[5, 6]]),
array([[15, 16],[20, 21]]),
array([[3, 4],[8, 9]]),
array([[18, 19],[23, 24]])]
Which I hope is what you are looking for.
To get the list of subset assuming you have the list of positions xList and yList, this will do the tric:
subsetList = [ data[y-size:y+size,x-size:x+size] for x,y in zip(xList,yList) ]
I have two numpy arrays x and y, which have length 10,000.
I would like to plot a random subset of 1,000 entries of both x and y.
Is there an easy way to use the lovely, compact random.sample(population, k) on both x and y to select the same corresponding indices? (The y and x vectors are linked by a function y(x) say.)
Thanks.
You can use np.random.choice on an index array and apply it to both arrays:
idx = np.random.choice(np.arange(len(x)), 1000, replace=False)
x_sample = x[idx]
y_sample = y[idx]
Just zip the two together and use that as the population:
import random
random.sample(zip(xs,ys), 1000)
The result will be 1000 pairs (2-tuples) of corresponding entries from xs and ys.
Update: For Python 3, you need to convert the zipped sequences into a list:
random.sample(list(zip(xs,ys)), 1000)
After test numpy.random.choice solution,
I found out it was very slow for larger array.
numpy.random.randint should be much faster
example
x = np.arange(1e8)
y = np.arange(1e8)
idx = np.random.randint(0, x.shape[0], 10000)
return x[idx], y[idx]
Using the numpy.random.randint function, you generate a list of random numbers, meaning that you can select certain datapoints twice.