I have a list of (x,y) values that are in a list like [(x,y),(x,y),(x,y)....]. I feel like there is a solution in matplotlib, but I couldn't quite get there because of my formatting. I would like to plot it as a histogram or line plot. Any help is appreciated.
You can quite easily convert a list of (x, y) tuples into a list of two tuples of x- and y- coordinates using the * ('splat') operator (see also this SO question):
>>> zip(*[(0, 0), (1, 1), (2, 4), (3, 9)])
[(0, 1, 2, 3), (0, 1, 4, 9)]
And then, you can use the * operator again to unpack those arguments into plt.plot
>>> plt.plot(*zip(*[(0, 0), (1, 1), (2, 4), (3, 9)]))
or even plt.bar
>>> plt.bar(*zip(*[(0, 0), (1, 1), (2, 4), (3, 9)]))
Perhaps you could try something like this (also see):
import numpy as np:
xs=[]; ys=[]
for x,y in xy_list:
xs.append(x)
ys.append(y)
xs=np.asarray(xs)
ys=np.asarray(ys)
plot(xs,ys,'ro')
Maybe not the most elegant solution, but it should work. Cheers, Trond
Related
I have a matrix A. I would like to generate the indices of all the values in this matrix.
A=np.array([[1,2,3],[4,5,6],[7,8,9]])
The desired output should look like:
[(0,0),(0,1),(0,2),(1,0),(1,1),(2,1),(2,0),(2,1),(2,2)]
You can use:
from itertools import product
list(product(*map(range, A.shape)))
This outputs:
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Explanation:
A.shape gives the dimensions of the array. For each dimension, we create a range() that generates all of the numbers between 0 and the length of a given dimension. We use map() to perform this for each dimension of the array. Finally, we unpack all of these ranges into the arguments of itertools.product() to create the Cartesian product among all these ranges.
Notably, the use of list unpacking and map() means that this approach can handle ndarrays with an arbitrary number of dimensions. At the time of posting this answer, all of the other answers cannot be immediately extended to a non-2D array.
This should work.
indices = []
for i in range(len(A)):
for j in range(len(A[i])):
indices.append((i,j))
Heres a way of doing by using itertools combinations
from itertools import combinations
sorted(set(combinations(tuple(range(A.shape[0])) * 2, 2)))
combinations chooses two elements from the list and pairs them, which results in duplication, so converting it to set to remove duplications and then sorting it.
This line of list comprehension works. It probably isn't as fast as using itertools, but it does work.
[(i,j) for i in range(len(A)) for j in range(len(A[i]))]
Using numpy only you can take advantage of ndindex
list(np.ndindex(A.shape))
or unravel_index:
list(zip(*np.unravel_index(np.arange(A.size), A.shape)))
Output:
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
NB. The second option enables you to pass a order='C' (row-major) or order='F' (column-major) parameter to get a different order of the coordinates
Example on A = np.array([[1,2,3],[4,5,6]])
order='C' (default):
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
order='F':
[(0, 0), (1, 0), (0, 1), (1, 1), (0, 2), (1, 2)]
I have some Python code that I would like to run in Matlab. Suppose you have two lists of the same length:
x = [0, 2, 2, 5, 8, 10]
y = [0,2, 4, 7, 3, 3]
P = np.copy(y)
P.sort()
P = np.unique(P, axis=0) # P = [0 2 3 4 7] Takes the list y, sorts it and removes repeated elements
s = list(zip(x,y)) #match list x with y: s = [(0, 0), (2, 2), (2, 4), (5, 7), (8, 3), (10, 3)]
for y_1,y_2 in zip(P,P[1:]): # runs over (0, 2), (2, 3), (3, 4), (4, 7)
for v_1,v_2 in zip(s, s[1:]):
-- process --
Where in this case:
list(zip(s, s[1:])) = [((0, 0), (2, 2)), ((2, 2), (2, 4)), ((2, 4), (5, 7)), ((5, 7), (8, 3)), ((8, 3), (10, 3))]
I would like to translate this in Matlab but I don't know how to replicate the zip function. Any ideas on how I can do this?
MATLAB doesn’t have a zip, but you can accomplish the same thing in various ways. I think that the simplest translation of
for y_1,y_2 in zip(P,P[1:]):
...
is
for ii = 1:numel(P)-1
y_1 = P(ii);
y_2 = P(ii+1);
...
And in general, iterating over zip(x,y) is accomplished by iterating over indices 1:numel(x), then using the loop index to index into the arrays x and y.
Here's an implementation of Python's zip function in Matlab.
function out = zip(varargin)
% Emulate Python's zip() function.
%
% Don't actually use this! It will be slow. Matlab code works differently.
args = varargin;
nArgs = numel(args);
n = numel(args{1});
out = cell(1, n);
for i = 1:n
blah = cell(1, nArgs);
for j = 1:nArgs
if iscell(args{j})
blah(j) = args{j}(i);
else
blah{j} = args{j}(i);
end
end
out{i} = blah;
end
end
But don't use it; the performance will be lousy. In Matlab, you want to keep things in parallel primitive arrays instead, and use vectorized operations on those. Or, if you have to, iterate over array indexes.
For image analysis i loaded up a float image with scipy imread.
Next, i had scipys argrelmax search for local maxima in axis 0 and 1 and stored the results as arrays of tuples.
data = msc.imread(prediction1, 'F')
datarelmax_0 = almax(data, axis = 0)
datarelmax_1 = almax(data, axis = 1)
how can i create a numpy array from both lists which contains only the tuples that are in both list?
Edit:
argrelmax creates a tuple with two arrays:
datarelmax_0 = ([1,2,3,4,5],[6,7,8,9,10])
datarelmax_1 = ([11,2,13,14,5], [11,7,13,14,10])
in want to create a numpy array that looks like:
result_ar[(2,7),(5,10)]
How about this "naive" way?
import numpy as np
result = np.array([x for x in datarelmax_0 if x in datarelmax_1])
Pretty simple. Maybe there's a better/faster/fancier way by using some numpy methods but this should work for now.
EDIT:
To answer your edited question, you can do this:
result = [x for x in zip(datarelmax_0[0], datarelmax_0[1]) if x in zip(datarelmax_1[0], datarelmax_1[1])]
This gives you
result = [(2, 7), (5, 10)]
If you convert it to a numpy array by using
result = np.array(result)
it looks like this:
result = array([[ 2, 7],
[ 5, 10]])
In case you are interested in what zip does:
>>> zip(datarelmax_0[0], datarelmax_0[1])
[(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
>>> zip(datarelmax_1[0], datarelmax_1[1])
[(11, 11), (2, 7), (13, 13), (14, 14), (5, 10)]
I have the following code that is generating a random number of tuples in order to create a connected undirect weighted graph.
for i in xrange(0,10):
for j in xrange(0, (int)(10*random.random())):
b = (int)(10*random.random())
j = [(i,b)]
print(j)
When I run this code I am able to randomly generate random vertices (x,y), however I am running into an issue in that my b variable has the possibility of repeating twice. For example I may get (6,3) followed by (6,3) which when I add weights would ruin the graphs I'm trying to create. Also I am sometimes running into issues where I might get (2,4) and then later get (4,2) which again ruins the graphs that I'm trying to create.
Does anyone know how I can keep vertices from repeating?
Use random.sample
>>> lst1 = random.sample(range(20), 10)
>>> lst2 = random.sample(range(20), 10)
>>> zip(lst1, lst2)
[(19, 5), (5, 11), (9, 19), (0, 9), (4, 6), (12, 0), (7, 12), (16, 1), (10, 7), (15, 16)]
You can change the list generated by range(20) to suit your set of vertices.
Don't generate a new vertex inside the for loop, since it may generate the same one again. (don't pick randomly off of the random.sample lists) Just generate them once and zip them together.
Since you want to remove duplicates of type (x, y) and (y, x). You can do something like the following. (or the simple in method works too)
>>> r = [(19, 5), (5, 11), (5, 19)]
>>> from itertools import groupby
>>> m = map(set, r)
>>> m
[set([19, 5]), set([11, 5]), set([19, 5])]
>>> sorted(m, key=lambda x: sum(x))
[set([11, 5]), set([19, 5]), set([19, 5])]
>>> [tuple(k) for k, v in groupby(sorted(m, key = lambda x: sum(x)))]
[(11, 5), (19, 5)]
I am new to python and don't know the best way to do this.
I have a list of tuples which represent points and another list which represents offsets. I need a set of all the combinations that this forms.
Here's some code:
offsets = [( 0, 0),( 0,-1),( 0, 1),( 1, 0),(-1, 0)]
points = [( 1, 5),( 3, 3),( 8, 7)]
So my set of combined points should be
[( 1, 5),( 1, 4),( 1, 6),( 2, 5),( 0, 5),
( 3, 3),( 3, 2),( 3, 4),( 4, 3),( 2, 3),
( 8, 7),( 8, 6),( 8, 8),( 9, 7),( 7, 7)]
I'm not able to use NumPy or any other libraries.
result = [(x+dx, y+dy) for x,y in points for dx,dy in offsets]
For more, see list comprehensions.
Pretty simple:
>>> rslt = []
>>> for x, y in points:
... for dx, dy in offsets:
... rslt.append( (x+dx, y+dy) )
...
>>> rslt
[(1, 5), (1, 4), (1, 6), (2, 5), (0, 5), (3, 3), (3, 2), (3, 4), (4, 3), (2, 3), (8, 7), (8, 6), (8, 8), (9, 7), (7, 7)]
Cycle through the points and the offsets, then build new tuples of adding the offsets to the points.
Personally, I like Alok's answer. However, for fans of itertools, the itertools-based equivalent (in Python 2.6 and later) is:
import itertools as it
ps = [(x+dx, y+dy) for (x, y), (dx, dy) in it.product(points, offsets)]
However, in this case the itertools solution is not faster than the simple one (it's actually a tad slower because it needs to unpack each x, y repeatedly for every offset, while Alok's simple approach unpacks each x, y but once). Still, itertools.product is an excellent alternative to nested loops in other cases, so, it's worth knowing about it!-)
If you don't care about duplicates in the result:
result = []
for ox, oy in offsets:
for px, py in points:
result.append((px + ox, py + oy))
If you do care about duplicates in the result:
result = set()
for ox, oy in offsets:
for px, py in points:
result.add((px + ox, py + oy))