Add text next to vertical line in matplotlib - python

Here is my code:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime
import numpy as np
fig, ax = plt.subplots(1,1)
sample_dates = np.array([datetime.datetime(2000,1,1), datetime.datetime(2001,1,1)])
sample_dates = mdates.date2num(sample_dates)
plt.vlines(x=sample_dates, ymin=0, ymax=10, color = 'r')
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%y'))
plt.show()
It plots two red lines at certain dates on x-axis. Now I would like to add text to every line. Text should be parallel to the line. Where do I start?

You can use Matplotlib text function to draw text on the plots. It has a lot of parameters that can be set. See documentation and examples here.
Here is an example with some text parallel to the lines:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime
import numpy as np
from matplotlib.pyplot import text
fig, ax = plt.subplots(1,1)
sample_dates = np.array([datetime.datetime(2000,1,1), datetime.datetime(2001,1,1)])
sample_dates = mdates.date2num(sample_dates)
plt.vlines(x=sample_dates, ymin=0, ymax=10, color = 'r')
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%y'))
for i, x in enumerate(sample_dates):
text(x, 5, "entry %d" % i, rotation=90, verticalalignment='center')
plt.show()
Should look like this:

Related

How animation scatter plot with Matplotlib can be done with not superimposed data?

I want to do an animated scatter plot with one only pair of x,y data for each frame.
The code I wrote creates an animated scatter plot but the old dots appear in the plot, that means that new dots are added on the plot, keeping the old ones.
For the code below I want a dot per frame like a moving dot on x axis and not adding one more value.
I tried with plt.clf() but then all data disappear.
%matplotlib notebook
from bokeh.plotting import figure, output_file, show
import pandas
import numpy as np
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter
import matplotlib.pyplot as plt
writer = PillowWriter(fps=10)
list_x=[1,2,3,4,5,6,7,8,9]
list_y=[5,5,5,5,5,5,5,5,5]
def plot(listax, listay):
plt.scatter(listax, listay, c='blue', alpha=0.5)
plt.show()
fig2 = plt.figure()
plt.xlim([0, 10])
plt.ylim([0, 10])
with writer.saving(fig2, "plotvideo.gif", 100):
for i in range(0, len(list_x)):
x_value = list_x[i]
y_value = list_y[i]
writer.grab_frame()
plot(x_value, y_value)
Use the .remove() method on the point objects to remove them from the figure.
I would try this:
from bokeh.plotting import figure, output_file, show
import pandas
import numpy as np
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter
import matplotlib.pyplot as plt
import time
writer = PillowWriter(fps=10)
list_x=[1,2,3,4,5,6,7,8,9]
list_y=[5,5,5,5,5,5,5,5,5]
points = []
def plot(listax, listay, j):
points.append(plt.scatter(listax[j], listay[j], c='blue', alpha=0.5))
if len(points) == 2:
points[0].remove()
points.pop(0)
plt.show(block=False)
fig2 = plt.figure()
plt.xlim([0, 10])
plt.ylim([0, 10])
with writer.saving(fig2, "plotvideo.gif", 100):
for i in range(0, len(list_x)):
x_value = list_x
y_value = list_y
writer.grab_frame()
print(points)
plot(x_value, y_value, i)
See this link for a better explanation (albeit with a different implementation):
How to remove points from a plot?

How to create specific plots using Pandas and then store them as PNG files?

So I am trying to create histograms for each specific variable in my dataset and then save it as a PNG file.
My code is as follows:
import pandas as pd
import matplotlib.pyplot as plt
x=combined_databook.groupby('x_1').hist()
x.figure.savefig("x.png")
I keep getting "AttributeError: 'Series' object has no attribute 'figure'"
Use matplotlib to create a figure and axis objects, then tell pandas which axes to plot on using the ax argument. Finally, use matplotlib (or the fig) to save the figure.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Sample Data (3 groups, normally distributed)
df = pd.DataFrame({'gp': np.random.choice(list('abc'), 1000),
'data': np.random.normal(0, 1, 1000)})
fig, ax = plt.subplots()
df.groupby('gp').hist(ax=ax, ec='k', grid=False, bins=20, alpha=0.5)
fig.savefig('your_fig.png', dpi=200)
your_fig.png
Instead of using *.hist() I would use matplotlib.pyplot.hist().
Example :
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
y =[10, 20,30,40,100,200,300,400,1000,2000]
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
ax.plot(x, y, label='$y = Values')
plt.title('my plot')
ax.legend()
plt.show()
fig.savefig('tada.png')

Scatter plot with colorbar and datetime axis ticks

I am getting lost in different methods used in matplotlib.
I want to create a colour-coded scatter plot with a colorbar on the side and datetime on the x axis.
But depending on how I define my ax, I get different errors.
Below is the core of my code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.cm as cm
import matplotlib.dates as mdates
#.....loading files etc.
norm = mcolors.Normalize(vmin=0,vmax=1000)
timerange = pd.date_range(start='2015-01-01', end='2016-01-01', freq='30D')
### PLOTTING
fig = plt.figure(figsize=(6.,5))
ax = fig.add_subplot(111)
for Af in Afiles:
for index, row in Af.iterrows():
time = pd.to_datetime(row['date'], format="%Y-%m-%d")
plt.scatter(time, row['A'], c=row['z'], norm=norm, cmap=colormap,edgecolor='k', lw=0.8, s=80)
plt.xticks(timerange, rotation=90)
ax.xaxis.set_major_formatter(mdates.DateFormatter("%d/%m/%Y"))
plt.xlabel('Time', fontsize=11, color='k')
clb = fig.colorbar(ax)
clb.ax.set_title('Value', y=-0.125, fontsize=11)
clb.ax.invert_yaxis()
fig.tight_layout()
this produces AttributeError: 'AxesSubplot' object has no attribute 'autoscale_None'
but if I specify my ax as the scatter plot so that I can get my colour-coding working, I then have trouble with the axis formatter.
Writing instead ax = plt.scatter generates AttributeError: 'PathCollection' object has no attribute 'xaxis'.
How can I have both the colorbar AND formatted axis ticks?
Don't call the scatter ax. (This overwrites the existinge axes ax.)
The colorbar expects as first argument a ScalarMappable (as e.g. the scatter). Since the scatters are all normalized, you can use it from the loop,
norm = plt.Normalize(...)
for bla in blubb:
scatter = plt.scatter(..., norm=norm)
Then,
clb = fig.colorbar(scatter)
The rest should stay the same.
The basic idea is that you need to add an extra axis for the colorbar.
It's hard to know if this is an exact match, as you haven't provided a working example with data. But this may at least serve as a template.
First, some example data:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.cm as cm
import matplotlib.dates as mdates
from mpl_toolkits.axes_grid1 import make_axes_locatable
vmin = 0
vmax = 1000
timerange = pd.date_range(start='2015-01-01', end='2016-01-01', freq='30D')
N = len(timerange)
data = np.random.randint(vmin, vmax, size=N)
# z contains the colorbar values for each point
cmap = plt.get_cmap('Reds')
z = [cmap((x-vmin)/(vmax-vmin))[:3] for x in data]
df = pd.DataFrame({"value":data, "datetime":timerange, "z":z})
Now plot:
fig = plt.figure(figsize=(6.,5))
ax = fig.add_subplot(111)
plt.scatter(x=df.datetime.values, y=df.value.values, c=df.z)
ax.set_xticklabels(timerange, rotation=90)
ax.xaxis.set_major_formatter(mdates.DateFormatter("%d/%m/%Y"))
ax.set_xlabel('Time')
Now add colorbar:
norm = mcolors.Normalize(vmin=vmin,vmax=vmax)
m = cm.ScalarMappable(cmap='Reds', norm=norm)
m.set_array([(x-vmin)/(vmax-vmin) for x in df.value.values])
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.1)
clb = plt.colorbar(m, cax=cax)

Using xkcd to plot a hr diagram but all the labels are so big

So I'm trying to plot a hr diagram in python using matplotlib and I want to make it look a little more appealing to children by making it look like a drawing with xkcd. I'm not getting any errors with my code but the axes labels and title on the resulting graph are so big you can't even read what they're saying. Does anyone know how I could fix this?
import glob
import pylab as plt
import numpy as np
import sys
import os
from sys import exit
import random
from numpy import exp
import math
from matplotlib import colors as mcolors
import csv
from matplotlib.ticker import ScalarFormatter
plt.xkcd()
plt.style.use('dark_background')
fig = plt.figure()
ax = fig.add_subplot(111)
with open("gaia_stars - Sheet1 (1).tsv") as tsvfile:
tsvreader = csv.reader(tsvfile, delimiter="\t")
tsvfile.next()
for line in tsvreader:
temperature.append(line[5])
magnitude.append(line[21])
plt.figure(figsize=(22,22))
plt.scatter(temperature, magnitude, c=temperature, cmap=plt.get_cmap('RdYlBu'), marker='*')
plt.ylabel('Magnitude',fontsize=17)
plt.xlabel('Temperature /K',fontsize=17)
plt.title('Hertzsprung-Russell Diagram',fontsize=20)
plt.gca().invert_xaxis()
plt.xscale('log')
plt.gca().invert_yaxis()
for line in ax.get_xticklines() + ax.get_yticklines():
line.set_markersize(10)
plt.tick_params(axis='x', which='major', labelsize=12)
plt.tick_params(axis='y', which='major', labelsize=12)
plt.tight_layout()
plt.show()

How do you create line segments between two points?

I have this bit of code that plots out the points:
import matplotlib.pyplot as plot
from matplotlib import pyplot
all_data = [[1,10],[2,10],[3,10],[4,10],[5,10],[3,1],[3,2],[3,3],[3,4],[3,5]]
x = []
y = []
for i in xrange(len(all_data)):
x.append(all_data[i][0])
y.append(all_data[i][1])
plot.scatter(x,y)
pyplot.show()
but I want all the possible lines that could be made that looks something like this:
I've tried matplotlib path, but it doesn't work well for me.
This can be optimized but it works:
for point in all_data:
for point2 in all_data:
pyplot.plot([point[0], point2[0]], [point[1], point2[1]])
import matplotlib.pyplot as plt
import itertools
fig=plt.figure()
ax=fig.add_subplot(111)
all_data = [[1,10],[2,10],[3,10],[4,10],[5,10],[3,1],[3,2],[3,3],[3,4],[3,5]]
plt.plot(
*zip(*itertools.chain.from_iterable(itertools.combinations(all_data, 2))),
color = 'brown', marker = 'o')
plt.show()
One other way could be to use matplotlib patches
import matplotlib
import pylab as pl
fig, ax = pl.subplots()
import matplotlib.patches as patches
from matplotlib.path import Path
verts = [(x1,y1), (x2,y2)]
codes = [Path.MOVETO,Path.LINETO]
path = Path(verts, codes)
ax.add_patch(patches.PathPatch(path, color='green', lw=0.5))
using all combinations?
import matplotlib.pyplot as plot
from matplotlib import pyplot
all_data = [[1,10],[2,10],[3,10],[4,10],[5,10],[3,1],[3,2],[3,3],[3,4],[3,5]]
x = []
y = []
for i in combinations(all_data,2):
x.extend(i[0])
y.extend(i[1])
plot.plot(x,y)
pyplot.show()

Categories