Incorrect matplotlib plot - python

I've been trying to make a simple plot on matplotlib with the following set of datapoints, but I'm getting an incorrect plot which is utterly baffling. The plot includes points that aren't in the set of datapoints.
The set of points I'm plotting are:
[(0, 0), (3, 0), (0, 0), (2, 0), (0, 0), (3, 0), (1, 0), (7, 0), (2, 0), (0, 0), (5, 0), (2, 1), (10, 1), (1, 0), (1, 0), (8, 0), (3, 0), (1, 0), (2, 0), (2, 0), (1, 0), (6, 1), (3, 0), (3, 0), (12, 1), (3, 0), (0, 0), (2, 0), (0, 0), (2, 0), (3, 1), (0, 0), (4, 0), (4, 0), (2, 0), (2, 0)]
And I'm simply calling:
plt.plot(pts, 'ro')
I'd love to know how I'm going wrong here. Thanks in advance.

Currently, matplotlib thinks that you're trying to plot each entry of the tuple against the index of the tuple. That is, your plot has the points (i, x_i) and (i, y_i) with 'i' going from 1 to 35.
As #jedwards pointed out, you could use the scatter function.
Or, you could make the plot function explicitly plot (x_i, y_i) by extracting each element of the tuple as follows:
import matplotlib.pyplot as plt
data = [(0, 0), (3, 0), (0, 0), (2, 0), (0, 0), (3, 0), (1, 0), (7, 0), (2, 0), (0, 0), (5, 0), (2, 1), (10, 1), (1, 0), (1, 0), (8, 0), (3, 0), (1, 0), (2, 0), (2, 0), (1, 0), (6, 1), (3, 0), (3, 0), (12, 1), (3, 0), (0, 0), (2, 0), (0, 0), (2, 0), (3, 1), (0, 0), (4, 0), (4, 0), (2, 0), (2, 0)]
plt.plot([int(i[0]) for i in data], [int(i[1]) for i in data], 'or')
plt.xlim(-1, 8) # Sets x-axis limits
plt.ylim(-1, 2) # Sets y-axis limits
plt.show() # Show the plot

"Set of points" makes me think you want a scatter plot instead. If you're expecting something like this:
Then you probably want pyplot's scatter() function.
import matplotlib.pyplot as plt
data = [(0, 0), (3, 0), (0, 0), (2, 0), (0, 0), (3, 0), (1, 0), (7, 0), (2, 0), (0, 0), (5, 0), (2, 1), (10, 1), (1, 0), (1, 0), (8, 0), (3, 0), (1, 0), (2, 0), (2, 0), (1, 0), (6, 1), (3, 0), (3, 0), (12, 1), (3, 0), (0, 0), (2, 0), (0, 0), (2, 0), (3, 1), (0, 0), (4, 0), (4, 0), (2, 0), (2, 0)]
x,y = zip(*data)
#plt.plot(data, 'ro') # is the same as
#plt.plot(x, 'ro') # this
plt.scatter(x, y) # but i think you want scatter
plt.show()
For plot() note:
If x and/or y is 2-dimensional, then the corresponding columns will be plotted.

Related

SageMath: Creating a list of vectors of an arbitrary dimension ranging from -a to +a

I would like to create a list of vectors of an arbitrary dimension n such that all of their entries range from an input -a to a. I know how to do this for a given dimension. For instance if n=2, the following does the job:
a = 1
[vector([x,y]) for x in [-a..a] for y in [-a..a]]
#output:
[(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 0), (0, 1), (1, -1), (1, 0), (1, 1)]
I am not sure how to extend this for an arbitrary n. I have used list comprehension, but it can be done in any other format. One idea that came to mind, which did not work was to use something like:
n = 2
letters = [chr(ord('`')+i+23) for i in [1..n]]
# output
# ['x', 'y']
a = 1
[vector([var(letters[0]),var(letters[1])]) for var(letters[0]) in [-a..a] for var(letters[1]) in [-a..a]]
# SyntaxError: can't assign to function call
Is there an efficient way of doing this in SageMath?
You can use itertools.product for this:
import itertools as it
def all_coords(a: int, ndim: int):
yield from it.product(range(-a + 1, a), repeat=ndim)
Usage:
>>> list(all_coords(2, ndim=2))
[(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 0), (0, 1), (1, -1), (1, 0), (1, 1)]
>>> list(all_coords(3, ndim=2))
[(-2, -2), (-2, -1), (-2, 0), (-2, 1), (-2, 2), (-1, -2), (-1, -1), (-1, 0), (-1, 1), (-1, 2), (0, -2), (0, -1), (0, 0), (0, 1), (0, 2), (1, -2), (1, -1), (1, 0), (1, 1), (1, 2), (2, -2), (2, -1), (2, 0), (2, 1), (2, 2)]
>>> list(all_coords(2, ndim=3))
[(-1, -1, -1), (-1, -1, 0), (-1, -1, 1), (-1, 0, -1), (-1, 0, 0), (-1, 0, 1), (-1, 1, -1), (-1, 1, 0), (-1, 1, 1), (0, -1, -1), (0, -1, 0), (0, -1, 1), (0, 0, -1), (0, 0, 0), (0, 0, 1), (0, 1, -1), (0, 1, 0), (0, 1, 1), (1, -1, -1), (1, -1, 0), (1, -1, 1), (1, 0, -1), (1, 0, 0), (1, 0, 1), (1, 1, -1), (1, 1, 0), (1, 1, 1)]

How to return a new list of lists in python correctly [duplicate]

I try to solve a problem and one part of it is to find all paths from (0, 0) to the right most point of the 2d array. This is my code:
def route_finder_helper(x, y, current_path, filler, list_of_lists):
current_path[filler] = (x, y)
if x == 0 and y == 0:
print(current_path)
list_of_lists.append(current_path)
return list_of_lists
if x == 0:
return route_finder_helper(x, y - 1, current_path, filler - 1, list_of_lists)
if y == 0:
return route_finder_helper(x - 1, y, current_path, filler - 1, list_of_lists)
return route_finder_helper(x-1, y, current_path, filler - 1, list_of_lists) + \
route_finder_helper(x, y-1, current_path, filler - 1, list_of_lists)
where x and y is current coordinate, current_path is a list of tuples of the current path, filler is index what position of the list to change and list_of_lists should be all the paths. However, when I run this program and print the return value I get this output:
[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]
[(0, 0), (0, 1), (1, 1), (1, 2), (2, 2)]
[(0, 0), (1, 0), (1, 1), (1, 2), (2, 2)]
[(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)]
[(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)]
[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]
[[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]]
So I get the correct paths, but I do not know how to save them to the list of lists. Could someone help me?
This is how I call my function:
x_coordinate = coordinates[0]
y_coordinate = coordinates[1]
path_length = (x_coordinate + 1) + (y_coordinate + 1) - 1
start_filling = path_length - 1
current_path = [0] * path_length
paths = route_finder_helper(x_coordinate, y_coordinate, current_path,
start_filling, [])
This is what it should return:
[[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)],[(0, 0), (0, 1), (1, 1), (1, 2), (2, 2)], [(0, 0), (1, 0), (1, 1), (1, 2), (2, 2)], [(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)], [(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]]
This is the corrected answer:
def route_finder_helper(x, y, current_path, filler, list_of_lists):
current_path[filler] = (x, y)
if x == 0 and y == 0:
return list_of_lists + [current_path[:]]
if x == 0:
return route_finder_helper(x, y - 1, current_path, filler - 1, list_of_lists)
if y == 0:
return route_finder_helper(x - 1, y, current_path, filler - 1, list_of_lists)
return route_finder_helper(x-1, y, current_path, filler - 1, list_of_lists) + \
route_finder_helper(x, y-1, current_path, filler - 1, list_of_lists)
x_coordinate = 2
y_coordinate = 2
path_length = (x_coordinate + 1) + (y_coordinate + 1) - 1
start_filling = path_length - 1
current_path = [0] * path_length
paths = route_finder_helper(x_coordinate, y_coordinate, current_path, start_filling, [])
print(paths)
Output:
[[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)],
[(0, 0), (0, 1), (1, 1), (1, 2), (2, 2)],
[(0, 0), (1, 0), (1, 1), (1, 2), (2, 2)],
[(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)],
[(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)],
[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]]
The correction here is:
return list_of_lists + [current_path[:]]
where I add a copy by using current_path[:]
The logic of the code is correct, the problem that you have is that you are dealing with a list which is a mutable item. This means that every variable which has a reference to the list, gets an updated list when you change it for only one variable:
a = [1, 2, 3]
b = a
a[0] = -1
print(b)
>>> [-1, 2, 3]
Something like this also happens in your code when you append to the list_of_lists. Simply changing the append to this:
# return list_of_lists.append(current_path) <- old code
return list_of_lists + [current_path] <- new code
This guarantees that you start a new list every time the code ends up there, instead of appending to a list where other parts of the code have a reference to as well.
If this is a new concept for you in Python there are plenty of nice blogs which explain this in more detail than me, e.g. here
complete code:
def route_finder_helper(x, y, current_path, filler, list_of_lists):
current_path[filler] = (x, y)
if x == 0 and y == 0:
return list_of_lists + [current_path]
if x == 0:
return route_finder_helper(x, y - 1, current_path, filler - 1, list_of_lists)
if y == 0:
return route_finder_helper(x - 1, y, current_path, filler - 1, list_of_lists)
return route_finder_helper(x-1, y, current_path, filler - 1, list_of_lists) + \
route_finder_helper(x, y-1, current_path, filler - 1, list_of_lists)
x_coordinate = 2
y_coordinate = 2
path_length = (x_coordinate + 1) + (y_coordinate + 1) - 1
start_filling = path_length - 1
current_path = [0] * path_length
paths = route_finder_helper(x_coordinate, y_coordinate, current_path, start_filling, [])
print(paths)
>>> [[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]]

networkx edges return wrong indices

I started using python and networkx from a few days.
I have an unoriented graph and I try to iterate on the edges incident to a node.
I used
print (G.edges)
for i in G.nodes:
print( G.edges(i))
obtaining
[(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
[(0, 1), (0, 2), (0, 4)]
[(1, 0), (1, 2), (1, 3), (1, 4)]
[(2, 0), (2, 1), (2, 3), (2, 4)]
[(3, 1), (3, 2), (3, 4)]
[(4, 0), (4, 1), (4, 2), (4, 3)]
The edges provided by G.edges() have the two nodes reversed in some cases (e.g., for i=1 I have edge (1,0), but it does not exist !! I have only (0,1). Since the graph is unoriented, it is the same edge, but if I try to use it as the index of a vector of the edges it does not work.
I tried
for i in G. nodes
... do something with .... x[e] for e in G.edges(i)
You can extend the list of G.edges() to be in both direction
a = [e for e in G.edges]
gives you the list of edges [(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] which removes duplicate representations of undirected edges while neighbor reporting across all nodes will naturally report both directions, according to networkx Documentation.
You can either:
1) duplicate the list by adding edges representation in reversed order
a = [e for e in G.edges] + [(y, x) for (x, y) in G.edges]
which gives you
[(0, 1), (0, 2), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), (1, 0), (2, 0), (4, 0), (2, 1), (3, 1), (4, 1), (3, 2), (4, 2), (4, 3)]
or; 2) use list comprehension to get edges from G.edges(i) like you did:
b = [e for i in G.nodes for e in G.edges(i)]
output:
[(0, 1), (0, 2), (0, 4), (1, 0), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 3), (2, 4), (3, 1), (3, 2), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3)]

Apply sum distrutively to tuples

I'd like to have an algorithm which calculates the transitions from these STATE/ACTIONS tuples. For example, if you are in state (2,1) you can transition to states [(2,2),(2,0)]. This is calculated by adding the actions [(0,1),(-1,0)], to the state (2,1). I'm somewhat new to python so I'm wondering what the most efficient way to do this is. I would end up with a dict similar to the ACTIONS dict. Thanks!!
STATES=[
(0,0),
(0,1),
(0,2),
(0,3),
(1,0),
# '1,1',
(1,2),
(1,3),
(2,0),
(2,1),
(2,2),
(2,3)
]
ACTIONS={
(0,0):[(0,1),(1,0)],
(0,1):[(0,1),(0,-1)],
(0,2):[(0,-1),(1,0),(0,1)],
(0,3):[(0,-1),(1,0)],
(1,0):[(1,0),(-1,0)],
# '1,1':0,
(1,2):[(1,0),(-1,0),(0,1)],
(1,3):[],
(2,0):[(0,1),(-1,0)],
(2,1):[(0,1),(0,-1)],
(2,2):[(0,-1),(-1,0),(0,1)],
(2,3):[]
}
You can set up a list of possible offsets corresponding to the actions available. From there, you build a dictionary of actions using the state as key.
STATES=[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
offsets = [(0, 1),(-1, 0), (1, 1), (-1, -1)]
actions = {}
for state in STATES:
actions[state] = [(state[0] + off0, state[1] + off1) for off0, off1 in offsets]
actions
output:
{(0, 0): [(0, 1), (-1, 0), (1, 1), (-1, -1)],
(0, 1): [(0, 2), (-1, 1), (1, 2), (-1, 0)],
(0, 2): [(0, 3), (-1, 2), (1, 3), (-1, 1)],
(0, 3): [(0, 4), (-1, 3), (1, 4), (-1, 2)],
(1, 0): [(1, 1), (0, 0), (2, 1), (0, -1)],
(1, 2): [(1, 3), (0, 2), (2, 3), (0, 1)],
(1, 3): [(1, 4), (0, 3), (2, 4), (0, 2)],
(2, 0): [(2, 1), (1, 0), (3, 1), (1, -1)],
(2, 1): [(2, 2), (1, 1), (3, 2), (1, 0)],
(2, 2): [(2, 3), (1, 2), (3, 3), (1, 1)],
(2, 3): [(2, 4), (1, 3), (3, 4), (1, 2)]}

Change values of a list of list (of tuples) in a for statement

I want to create an object to store the positions of some creatures of a game.
A list of lists of tuples seemed appropriate to me. The matrix created by the list of lists represents the board of the game, element of it being a tuple of 2 variables ('type', number). For example: ('h', 3) would mean: 'there are 3 humans here'.
So here is how I initialize the board:
>>>lines = 5
>>>columns = 5
>>>board= [[(0,0)]*lines]*columns
>>>pprint(board)
[[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]]
Then I want to put some humans in my board:
>>> board[2][2]=('h',3)
I expect the board to be:
[[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), ('h', 3), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]]
but instead, when I do >>> pprint(board), it returns:
[[(0, 0), (0, 0), ('h', 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), ('h', 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), ('h', 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), ('h', 0), (0, 0), (0, 0)],
[(0, 0), (0, 0), ('h', 0), (0, 0), (0, 0)]]
I don't understand why all the elements of board are modified, this is very very frustrating. I am certainly missing something here, thanks for your help.
The following:
board = [[(0,0)]*lines]*columns
should become
board = [[(0,0)]*lines for _ in range(columns)]
Otherwise the top-level list consists of references to the same sublist:
In [7]: lines = 3
In [8]: columns = 4
In [9]: board = [[(0,0)]*lines]*columns
In [10]: map(id, board)
Out[10]: [18422120, 18422120, 18422120, 18422120]
In this setup, when you change one sublist, they all change.

Categories