Visualizing data

Matplotlib

Let’s check the matplotlib quick start guide!

Other libraries

Seaborn:

  • Seaborn is a statistical data visualization library built on top of Matplotlib, and simplifies the creation of complex visualizations like heatmaps, violin plots, and pair plots.
  • Provides themes and color palettes that improve the aesthetics of plots.
  • Best suited for statistical data exploration and analysis.

Plotly

  • A library for creating web-based interactive plots and dashboards. It is very useful for web applications, presentations and notebooks.
  • Whereas matplotlib’s output is mostly a static image, see, for example, the output of plotly:
import plotly.graph_objects as go

# Sample data
x = [1, 2, 3, 4, 5]
y = [10, 12, 8, 15, 11]

# Create a figure
fig = go.Figure()

# Add a line trace
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='line'))

# Update layout
fig.update_layout(title='Basic Line Chart', xaxis_title='x-axis', yaxis_title='y-axis')

# Show the plot
fig.show()

Example: basketball player statistics

One common application of NumPy in sports analytics is in analyzing player performance statistics. Let’s consider an example where we have a dataset of basketball players and their performance in terms of points scored, rebounds, and assists. We’ll use NumPy to calculate some basic statistics and visualize the data.

import numpy as np
import matplotlib.pyplot as plt

# Sample data: player performance (points, rebounds, assists)
player_data = np.array([
    [20, 5, 3],
    [15, 7, 2],
    [25, 3, 5],
    [18, 6, 4],
    [22, 4, 6]
])

# Calculate the mean, median, and standard deviation for each stat
mean_stats = np.mean(player_data, axis=0)
median_stats = np.median(player_data, axis=0)
std_stats = np.std(player_data, axis=0)

print("Mean:", mean_stats)
print("Median:", median_stats)
print("Standard Deviation:", std_stats)

# Plot the data
plt.figure(figsize=(10, 6))
plt.bar(np.arange(3)-0.2, mean_stats, width=0.2, label='Mean', align='center')
plt.bar(np.arange(3), median_stats, width=0.2, label='Median', align='center')
plt.bar(np.arange(3)+0.2, std_stats, width=0.2, label='Standard Deviation', align='center')
plt.xticks(np.arange(3), ['Points', 'Rebounds', 'Assists'])
plt.ylabel('Value')
plt.title('Player Performance Statistics')
plt.legend()
plt.show()
Mean: [20.  5.  4.]
Median: [20.  5.  4.]
Standard Deviation: [3.40587727 1.41421356 1.41421356]

In this example, we first create a NumPy array player_data representing the performance of five basketball players in terms of points, rebounds, and assists. We then use NumPy to calculate the mean, median, and standard deviation for each statistic across all players.

Finally, we use Matplotlib to plot a bar chart showing these statistics for each category (points, rebounds, assists). The bar chart compares the mean, median, and standard deviation for each category, providing a visual comparison of player performance statistics.

Example: calculating angles for a robot arm

In robotics, a common application of linear systems is in robot kinematics, specifically in calculating the inverse kinematics of a robot manipulator. Inverse kinematics involves determining the joint angles required to position the end-effector (e.g., robot gripper) at a desired position and orientation.

Let’s consider a simple 2D robotic arm with two joints. Given the lengths of the two links and the coordinates of the end-effector in the robot’s workspace, we can calculate the joint angles required to reach that position.

Assume the following parameters for the robot: - Length of the first link: \(L_1 = 1\) - Length of the second link: \(L_2 = 1\)

Let \((x, y)\) be the coordinates of the end-effector in the robot’s workspace. The forward kinematics equations for the end-effector position are given by:

\[ x = L_1 \cos(\theta_1) + L_2 \cos(\theta_1 + \theta_2) \]

\[ y = L_1 \sin(\theta_1) + L_2 \sin(\theta_1 + \theta_2) \]

Given \(x\) and \(y\), we can solve these equations to find \(\theta_1\) and \(\theta_2\) using NumPy.

import numpy as np

# Robot parameters
L1 = 1
L2 = 1

# End-effector position
x = 1
y = 1

# Calculate inverse kinematics
r = np.sqrt(x**2 + y**2)
theta2 = np.arccos((L1**2 + L2**2 - r**2) / (2 * L1 * L2))
theta1 = np.arctan2(y, x) - np.arctan2(L2 * np.sin(theta2), L1 + L2 * np.cos(theta2))

# Convert angles to degrees for easier interpretation
theta1_deg = np.degrees(theta1)
theta2_deg = np.degrees(theta2)

# Print the joint angles
print("Joint angles (theta1, theta2) in degrees:")
print(theta1_deg, theta2_deg)
Joint angles (theta1, theta2) in degrees:
-6.3611093629270335e-15 90.00000000000001

We can create an interactive visualization of this problem:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

# Robot parameters
L1 = 1
L2 = 1

# Initial x and y positions
x_init = 1
y_init = 1

# Calculate initial theta angles
theta1_init = np.degrees(np.arctan2(y_init, x_init))
D = (x_init**2 + y_init**2 - L1**2 - L2**2) / (2 * L1 * L2)
theta2_init = np.degrees(np.arccos(D))

# Create figure and axis
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
ax.grid(True)

# Initialize plot elements
link1, = ax.plot([], [], 'o-', color='blue', lw=2, markersize=8)
link2, = ax.plot([], [], 'o-', color='red', lw=2, markersize=8)
ee, = ax.plot([], [], 'o', color='green', markersize=8)

# Update function
def update(val):
    x = slider_x.val
    y = slider_y.val

    theta1 = np.degrees(np.arctan2(y, x))
    D = (x**2 + y**2 - L1**2 - L2**2) / (2 * L1 * L2)
    theta2 = np.degrees(np.arccos(D))

    # Calculate end-effector position
    x_end = L1 * np.cos(np.radians(theta1)) + L2 * np.cos(np.radians(theta1) + np.radians(theta2))
    y_end = L1 * np.sin(np.radians(theta1)) + L2 * np.sin(np.radians(theta1) + np.radians(theta2))

    # Update plot elements
    link1.set_data([0, L1 * np.cos(np.radians(theta1))], [0, L1 * np.sin(np.radians(theta1))])
    link2.set_data([L1 * np.cos(np.radians(theta1)), x_end], [L1 * np.sin(np.radians(theta1)), y_end])
    ee.set_data(x_end, y_end)

    fig.canvas.draw_idle()

# Create sliders
ax_slider_x = plt.axes([0.1, 0.1, 0.65, 0.03])
ax_slider_y = plt.axes([0.1, 0.05, 0.65, 0.03])
slider_x = Slider(ax_slider_x, 'X', -2, 2, valinit=x_init)
slider_y = Slider(ax_slider_y, 'Y', -2, 2, valinit=y_init)

slider_x.on_changed(update)
slider_y.on_changed(update)

plt.show()