I tried to create a graph side by side using matplotlib.
I don't get any errors when I run my code, instead, I just get a blank window from MatPlotLib.
Here's the link I used for my CSV.
https://ca.finance.yahoo.com/quote/%5EGSPTSE/history?p=%5EGSPTSE
Previously, I have also created a graph that overlayed the two lines(which works as intended), but they are not displaying as seperate graphs, which is what I am trying to do with my current code.
I tried this video for information in creating these graphs, but I can't replicate the graph shown in the video even when I copy the code.
https://www.youtube.com/watch?v=-2AMr95nUDw
from matplotlib import pyplot as mpl
import pandas as pd
data_better = pd.read_csv('What.csv')
# print(data_better.head()) #I used this part to find out what the headers were for x values
# print(data_better.columns[::])
mpl.axes([15000, 17000, 20000, 23000])
mpl.title("Open Values")
mpl.plot(data_better["Date"], data_better["Open"])
mpl.ylabel("Money")
mpl.axes([15000, 17000, 20000, 23000])
mpl.title("Close Values")
mpl.plot(data_better["Date"], data_better["Close"])
mpl.ylabel("Money")
mpl.show()
pyplot.axes accepts 4-tuple of floats in normalized (0, 1) units to place the axes. You can look at examples in Make Room For Ylabel Using Axesgrid to learn using it.
If you want to plot two plots in one figure, you need use different axes
from matplotlib import pyplot as plt
import pandas as pd
data_better = pd.read_csv('What.csv')
figure, (axes1, axes2) = plt.subplots(nrows=1, ncols=2)
axes1.set_title("Open Values")
axes1.plot(data_better["Date"], data_better["Open"])
axes1.set_ylabel("Money")
axes2.set_title("Close Values")
axes2.plot(data_better["Date"], data_better["Close"])
axes2.set_ylabel("Money")
plt.show()
Related
I am trying to generate a matplotlib plot that consists of two subplots that share an x-axis.
One subplot plots two sets of data on different y-axis scales, and the other just plots one set of data.
I would also like to "break" the x-axis of both subplots to account for a large period of time in between measurements in my data.
I have tried using the solution presented in this post, but as one poster claims, this method does not properly scale subplot x-axes.
I have been trying to use the brokenaxes package. It seems to create multiple subplots, scale them accordingly, and hide extraneous spines, ticks, and tick labels automatically.
This package doesn't seem to support sharing an x-axis (sharex) with subplots created from GridSpec.
Additionally, the method twinx does not work natively on a brokenaxes object. However each brokenaxes object contains a list of subplot axes objects. Each axes object can be used to generate a twinx, although this results in matplotlib rescaling subplots, redrawing spines, tick marks, and labels.
I have attempted to manually hide all the redrawn elements, however I'm still having trouble with a few things.
The lines that denote the broken axis are placed in an incorrect location
I have left y-axis tick marks on the top right subplot that I can't hide
The gridlines on the top right subplot are incorrect and inconsistent with the x-axis on the bottom subplot.
I want to use a date formatter using '%m-%d' for the x-axis ticks, but I'm getting an error attempting it:
AttributeError: 'CallCurator' object has no attribute 'set_major_formatter
Here is the result of my attempts:
And the pickled pandas data and code
used to generate it:
#!/usr/bin/env python3
import matplotlib as mpl
font= {'family': 'Arial',
'size': 7}
mpl.rc('font', **font)
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from matplotlib.ticker import NullFormatter
import matplotlib.dates as md
from brokenaxes import brokenaxes
import datetime
from pytz import timezone
import numpy as np
from pytz import timezone
import pandas as pd
from glob import glob
volt_color= 'tab:blue'
volt_style = 'solid'
amp_color = 'tab:red'
amp_style='dashed'
# starting date
start = pd.to_datetime("2020-05-20 15:40:09.059089184-07:00", infer_datetime_format=True).to_pydatetime()
start = timezone('US/Pacific').localize(start)
# load data
mudbat_data = pd.read_pickle("mudbat_data.pkl")
# perform rolling mean over data
mv = mudbat_data.rolling(5*60).mean()
# instantiate figures, and broken axes subplots
fig = plt.figure(figsize=(4,2))
gs = GridSpec(2,1)
tz = timezone('US/Pacific')
print(start)
[x1, x2, x3, x4] = [start, datetime.datetime(2020,5,27,tzinfo=tz), datetime.datetime(2020,7,20,tzinfo=tz),datetime.datetime(2020,7,22,tzinfo=tz)]
bax1 = brokenaxes(xlims=((x1,x2),(x3,x4)), subplot_spec=gs[0])
bax3 = brokenaxes(xlims=((x1,x2),(x3,x4)), subplot_spec=gs[1])
# plot first data
bax1.set_ylabel('Cell Voltage (V)')
bax1.plot(mv.index, mv['voltage'], color=volt_color, ls=volt_style)
bax1.tick_params(axis='y', labelcolor=volt_color)
bax1.grid(True)
# ensure all extraneous ticks for bax1 are hidden
bax1.axs[0].yaxis.tick_left()
bax1.axs[0].xaxis.set_ticklabels([])
bax1.axs[0].xaxis.set_ticklabels([])
bax1.axs[0].xaxis.set_ticks_position('none')
bax1.axs[0].yaxis.set_ticks_position('none')
bax1.axs[1].xaxis.set_ticklabels([])
bax1.axs[1].yaxis.set_ticklabels([])
bax1.axs[1].xaxis.set_ticks_position('none')
bax1.axs[1].yaxis.set_ticks_position('none')
# generate bax2 from bax1 axes
bax2 = []
for ax in bax1.axs:
bax2.append(ax.twinx())
# plot data on bax2 subplots
bax2[0].plot(mv.index, -1E6*mv['current'], color=amp_color, ls=amp_style)
bax2[1].plot(mv.index, -1E6*mv['current'], color=amp_color, ls=amp_style)
bax2[1].set_ylabel('Harvesting Current (μA)')
bax2[1].tick_params(axis='y', labelcolor=amp_color)
# hide generated spines and ticks/labels
bax2[0].spines['right'].set_visible(False)
bax2[0].yaxis.set_ticklabels([])
bax2[0].xaxis.set_ticklabels([])
bax2[0].xaxis.set_ticks_position('none')
bax2[0].yaxis.set_ticks_position('none')
bax2[1].spines['left'].set_visible(False)
bax2[1].xaxis.set_ticklabels([])
bax2[1].xaxis.set_ticks_position('none')
bax2[1].yaxis.tick_right()
# I would like to use this formatter
#bax3.xaxis.set_major_formatter(md.DateFormatter('%m-%d'))
bax3.set_ylabel("Power (uW)")
bax3.grid(True)
bax3.plot(mv.index, 1E6*mv['power'])
bax3.tick_params(axis='x', labelsize=6, rotation=45)
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
plt.subplots_adjust(hspace=0)
plt.savefig('plot.png', dpi=300)
Thank you for any help or suggestions you can give!
I'm a R programmer learning python and finding the plotting in python much more difficult than R.
I'm trying to write the following function but haven't been successful. Could anyone help?
import pandas as pd
#example data
df1 = pd.DataFrame({
'PC1':[-2.2,-2.0,2.04,0.97],
'PC2':[0.5,-0.6,0.9,-0.5],
'PC3':[-0.1,-0.2,0.2,0.8],
'f1':['a','a','b','b'],
'f2':['x','y','x','y'],
'f3':['k','g','g','k']
})
def drawPCA(df,**kwargs):
"""Produce a 1x3 subplots of scatterplot; each subplot includes two PCs with
no legend, e.g. subplot 1 is PC1 vs PC2. The legend is on the upper middle of
the figure.
Parameters
----------
df: Pandas DataFrame
The first 3 columns are the PCs, followed by sample characters.
kwargs
To specify hue,style,size, etc. if the plotting uses seaborn.scatterplot;
or c,s,etc. if using pyplot scatter
Example
----------
drawPCA(df1, hue="f1")
drawPCA(df1, c="f1", s="f2") #if plotting uses plt.scatter
drawPCA(df1, hue="f1", size="f2",style="f3")
or more varialbes passable to the actual plotting function
"""
This is what I come up with! Just two question:
is there a parameter to set the legend horizontal, instead of using the ncol?
how to prevent the figure from being displayed when running the function like this?
fig,ax=drawPCA(df1,hue="f1",style="f2",size="f3")
#may do more changing on the figure.
Here is the function:
def drawPCA2(df,**kwargs):
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.figure import figaspect
nUniVals=sum([df[i].unique().size for i in kwargs.values()])
nKeys=len(kwargs.keys())
w, h = figaspect(1/3)
fig1, axs = plt.subplots(ncols=3,figsize=(w,h))
fig1.suptitle("All the PCs")
sns.scatterplot(x="PC1",y="PC2",data=df,legend=False,ax=axs[0],**kwargs)
sns.scatterplot(x="PC1",y="PC3",data=df,legend=False,ax=axs[1],**kwargs)
sns.scatterplot(x="PC2",y="PC3",data=df,ax=axs[2],label="",**kwargs)
handles, labels = axs[2].get_legend_handles_labels()
fig1.legend(handles, labels, loc='lower center',bbox_to_anchor=(0.5, 0.85), ncol=nUniVals+nKeys)
axs[2].get_legend().remove()
fig1.tight_layout(rect=[0, 0.03, 1, 0.9])
return fig1,axs
I have a conceptual problem in the basic structure of matplotlib.
I want to add a Caption to a graph and I do understand the advice given in Is there a way of drawing a caption box in matplotlib
However, I do not know, how to combine this with the pandas data frame I have.
Without the structure given in the link above my code looks (projects1 being my pandas data frame):
ax2=projects1.T.plot.bar(stacked=True)
ax2.set_xlabel('Year',size=20)
and it returns a barplot.
But if I want to apply the structure of above, I get stuck. I tried:
fig = plt.figure()
ax2 = fig.add_axes((.1,.4,.8,.5))
ax2.plot.bar(projects1.T,stacked=True)
And it results in various errors.
So the question is, how do I apply the structure of the link given above with pandas data frame and with more complex graphs than a mere line. Thx
Pandas plot function has an optional argument ax which can be used to supply an externally created matplotlib axes instance to the pandas plot.
import matplotlib.pyplot as plt
import pandas as pd
projects1 = ...?
fig = plt.figure()
ax2 = fig.add_axes((.1,.4,.8,.5))
projects1.T.plot.bar(stacked=True, ax = ax2)
ax2.set_xlabel('Year',size=20)
I want to plot an image and a pandas bar plot side by side in an iPython notebook. This is part of a function so that the dataframe containing the values for the bar chart can vary with respect to number of columns.
The libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
Dataframe
faces = pd.Dataframe(...) # return values for 8 characteristics
This returns the the bar chart I'm looking for and works for a varying number of columns.
faces.plot(kind='bar').set_xticklabels(result[0]['scores'].keys())
But I didn't find a way to plot it in a pyplot figure also containing the image. This is what I tried:
fig, (ax_l, ax_r) = plt.subplots(nrows=1, ncols=2, figsize=(15, 5))
ax_l.imshow( img )
ax_r=faces.plot(kind='bar').set_xticklabels(result[0]['scores'].keys())
The output i get is the image on the left and an empty plot area with the correct plot below. There is
ax_r.bar(...)
but I couldn't find a way around having to define the columns to be plotted.
You just need to specify your axes object in your DataFrame.plot calls.
In other words: faces.plot(kind='bar', ax=ax_r)
I need to plot multiple sets of data on the same plot, and I use matplotlib.
For some of plots I use plt.plot() and for the others I use plt.errorbar(). But when I make a legend the ones created with plt.plot() appears first, no matter in which order I put them in the file (and zorder seems to have no effect on the position in the legend).
How can I give the order that I want in the legend, regardless of the way I plot the data?
You can adjust the order manually, by getting the legend handles and labels using ax.get_legend_handles_labels, and then reordering the resulting lists, and feeding them to ax.legend. Like so:
import matplotlib.pyplot as plt
import numpy as np
fig,ax = plt.subplots(1)
ax.plot(np.arange(5),np.arange(5),'bo-',label='plot1')
ax.errorbar(np.arange(5),np.arange(1,6),yerr=1,marker='s',color='g',label='errorbar')
ax.plot(np.arange(5),np.arange(2,7),'ro-',label='plot2')
handles,labels = ax.get_legend_handles_labels()
handles = [handles[0], handles[2], handles[1]]
labels = [labels[0], labels[2], labels[1]]
ax.legend(handles,labels,loc=2)
plt.show()