Search code examples
pythonpython-3.xpygal

Python Crash Course 15.10, visualizing Random Walk using pygal


I am going through the book "Python Crash Course", and i'm trying to visualise a random walk with pygal.(exercise 15.10).

Here is my code:

from random import choice

class RandomWalk():
    """A class to generate random walks."""

    def __init__(self, num_points=500):
        """Initialize attributes of a walk."""
        self.num_points = num_points

        # All walks start at (0, 0).
        self.x_values = [0]
        self.y_values = [0]
        
    def get_step(self):
       
        direction = choice([1,-1])
        distance = choice([0, 1, 2, 3, 4])
        step = direction * distance
        return step
        
        
    def fill_walk(self):
        """Calculate all the points in the walk."""

        # Keep taking steps until the walk reaches the desired length.
        while len(self.x_values) < self.num_points:
            # Decide which direction to go and how far to go in that direction.

            x_step = self.get_step()
            y_step = self.get_step()

            # Reject moves that go nowhere.
            if x_step == 0 and y_step == 0:
                continue

            # Calculate the next x and y values.
            next_x = self.x_values[-1] + x_step
            next_y = self.y_values[-1] + y_step

            self.x_values.append(next_x)
            self.y_values.append(next_y)
            
#Visualizing with Pygal
import pygal

while True:
    rw = RandomWalk()
    rw.fill_walk()
    xy_chart=pygal.XY()
    xy_chart.title = 'Random Walk'
    rwValues=list(zip(rw.x_values,rw.y_values))
    xy_chart.add('rw',rwValues)
xy_chart.render_to_file('rw_visual.svg')

The logistics of the random walk code is fine, however I can't seem to understand how to visualize it with pygal. Whenever I run the code (on Jupyter notebook), the notebook doesn't process it. I have tried visualizing it with matplotlib and everything is fine. If someone could explain what i'm doing wrong that would be great. The visualization with matplotib code is:

import matplotlib.pyplot as plt

# Keep making new walks, as long as the program is active.
while True:
    rw = RandomWalk()
    rw.fill_walk()
    plt.figure(figsize=(10, 10))
    point_numbers = list(range(rw.num_points))
    plt.plot(rw.x_values, rw.y_values,linewidth=1)
    plt.scatter(0, 0, c='green', edgecolors='none', s=100)
    plt.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none',
        s=100)
    plt.axes().get_xaxis().set_visible(False)
    plt.axes().get_yaxis().set_visible(False)
    plt.show()
    keep_running = input("Make another walk? (y/n): ")
    if keep_running == 'n':
        break

This runs just fine.


Solution

  • This is because Jupyter by default cannot render SVG image on output cell, so you need to tweak your code such that it is readable by IPython console. Here is what you can do:

    from IPython.display import HTML, display, SVG
    import pygal
    
    while True:
        rw = RandomWalk()
        rw.fill_walk()
        xy_chart = pygal.XY()
        xy_chart.title = 'Random Walk'
        rwValues = list(zip(rw.x_values, rw.y_values))
        xy_chart.add('rw', rwValues)
        keep_running = input("Make another walk? (y/n): ")
        if keep_running == 'n':
            display({'image/svg+xml': xy_chart.render()}, raw=True)
            # OR
            xy_chart.render_in_browser()
            # OR
            display(SVG(xy_chart.render(disable_xml_declaration=True)))
            break