Asked  6 Months ago    Answers:  5   Viewed   60 times

I have an array of timestamps in the format (HH:MM:SS.mmmmmm) and another array of floating point numbers, each corresponding to a value in the timestamp array.

Can I plot time on the x axis and the numbers on the y-axis using Matplotlib?

I was trying to, but somehow it was only accepting arrays of floats. How can I get it to plot the time? Do I have to modify the format in any way?

 Answers

23

You must first convert your timestamps to Python datetime objects (use datetime.strptime). Then use date2num to convert the dates to matplotlib format.

Plot the dates and values using plot_date:

dates = matplotlib.dates.date2num(list_of_datetimes)
matplotlib.pyplot.plot_date(dates, values)
Tuesday, June 1, 2021
 
mikelovelyuk
answered 6 Months ago
37

I don't think tsplot is going to work with the data you have. The assumptions it makes about the input data are that you've sampled the same units at each timepoint (although you can have missing timepoints for some units).

For example, say you measured blood pressure from the same people every day for a month, and then you wanted to plot the average blood pressure by condition (where maybe the "condition" variable is the diet they are on). tsplot could do this, with a call that would look something like sns.tsplot(df, time="day", unit="person", condition="diet", value="blood_pressure")

That scenario is different from having large groups of people on different diets and each day randomly sampling some from each group and measuring their blood pressure. From the example you gave, it seems like your data are structured like the this.

However, it's not that hard to come up with a mix of matplotlib and pandas that will do what I think you want:

# Read in the data from the stackoverflow question
df = pd.read_clipboard().iloc[1:]

# Convert it to "long-form" or "tidy" representation
df = pd.melt(df, id_vars=["date"], var_name="condition")

# Plot the average value by condition and date
ax = df.groupby(["condition", "date"]).mean().unstack("condition").plot()

# Get a reference to the x-points corresponding to the dates and the the colors
x = np.arange(len(df.date.unique()))
palette = sns.color_palette()

# Calculate the 25th and 75th percentiles of the data
# and plot a translucent band between them
for cond, cond_df in df.groupby("condition"):
    low = cond_df.groupby("date").value.apply(np.percentile, 25)
    high = cond_df.groupby("date").value.apply(np.percentile, 75)
    ax.fill_between(x, low, high, alpha=.2, color=palette.pop(0))

This code produces:

enter image description here

Sunday, June 13, 2021
 
Santi
answered 6 Months ago
95

The AttributeError: App instance has no attribute 'canvas' means that your code references the canvas attribute before it has been created/assigned.

This line:

self.button_left = Button(frame,text="< Previous Event",
                                    command=self.decrease(event_num))

is calling the decrease method because you used parentheses and provided arguments instead of just binding the handler. Inside the decrease method, you're accessing self.canvas to call the draw method.

That is happening before you create the canvas attribute, which happens on this line:

self.canvas = FigureCanvasTkAgg(fig,master=master)

Make event_num an attribute of the App object; then you won't have to pass arguments to the handler when you bind it. You can do this by assigning self.event_num = 1 inside __init__.

Sunday, August 29, 2021
 
Matt Bullock
answered 3 Months ago
50

The pylab.scatter function takes a value size based on the size in points^2. This size will be independent of the axes, as is the nature of a scatter plot (it doesn't make sense if you narrow in on a region in a scatter plot that the points get bigger).

If you want to say draw circles that are a given size, you should use the circle command in pylab

import pylab
axes = pylab.axes()
circle1 = pylab.Circle((0,0), radius=20, alpha=.5)
circle2 = pylab.Circle((0.5,0.5), radius=20, alpha=.5)
axes.add_patch(circle1)
axes.add_patch(circle2)
pylab.axis('scaled')
pylab.show()

If you need something with scatter plot like ability, you could do something like

import pylab
import matplotlib

def my_circle_scatter(axes, x_array, y_array, radius=0.5, **kwargs):
    for x, y in zip(x_array, y_array):
        circle = pylab.Circle((x,y), radius=radius, **kwargs)
        axes.add_patch(circle)
    return True

def my_square_scatter(axes, x_array, y_array, size=0.5, **kwargs):
    size = float(size)
    for x, y in zip(x_array, y_array):
        square = pylab.Rectangle((x-size/2,y-size/2), size, size, **kwargs)
        axes.add_patch(square)
    return True

def my_polygon_scatter(axes, x_array, y_array, resolution=5, radius=0.5, **kwargs):
    ''' resolution is number of sides of polygon '''
    for x, y in zip(x_array, y_array):
        polygon = matplotlib.patches.CirclePolygon((x,y), radius=radius, resolution=resolution, **kwargs)
        axes.add_patch(polygon)
    return True

axes=pylab.axes()
my_circle_scatter(axes, [0,0.5], [0,0.5], radius=2, alpha=.5, color='b')
my_square_scatter(axes, [-3,-4,2,3], [1,-3,0,3], size=.5, alpha=.5, color='r')
my_polygon_scatter(axes, [-1,-2,3], [-3,0,3], radius=.5, resolution=3, alpha=.5, color='g')
my_polygon_scatter(axes, [4,1.5,3], [2,-1,-3], radius=.5, resolution=5, alpha=.5, color='k')
pylab.axis('scaled')
pylab.axis([-5,5,-5,5])
pylab.show()

See http://matplotlib.sourceforge.net/api/artist_api.html#module-matplotlib.patches for other drawable objects.

Sample output from first snippet: matplotlib circles

Sample output from second snippet: matplotlib scatter plot

EDIT for Griff: If you want to handle a different radius for each point, you can do something straightforward like:

def my_circle_scatter_radii(axes, x_array, y_array, radii_array, **kwargs):
    for (x, y, r) in zip(x_array, y_array, radii_array):
        circle = pylab.Circle((x,y), radius=r, **kwargs)
        axes.add_patch(circle)
    return True

The logic to handle both cases simultaneously is also straightforward (e.g., check if its an radii_array is an int/float and if so make it an array).

Wednesday, September 15, 2021
 
Manse
answered 3 Months ago
30

If I understand you right, the confusion is which axis is which, right? If this is the case, you can easily plot a known asymmetric shape and the plot will tell you everything. For example, adopting an example from the gallery:

# By Armin Moser

from mpl_toolkits.mplot3d import Axes3D
import matplotlib
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# create supporting points in polar coordinates
r = np.linspace(0,1.25,50)
p = np.linspace(0,2*np.pi,50)
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = R*np.cos(P),R*np.sin(P)

#Z = ((R**2 - 1)**2)
Z = (X**2 + 0.2*Y**2 -1)**2   # <------- edit

ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet)
#ax.set_zlim3d(0, 1)
ax.set_xlabel(r'$phi_mathrm{real}$')
ax.set_ylabel(r'$phi_mathrm{im}$')
ax.set_zlabel(r'$V(phi)$')
plt.show()
Monday, November 15, 2021
 
Durandal
answered 2 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share