import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("population.csv")
fig, axs = plt.subplots(nrows=2, ncols=2)
for col, ax in zip(df.columns, axs.flatten()):
ax.plot(x,y)
ax.set_title(col)
plt.subplots_adjust(wspace=.5, hspace=.5)
fig.tight_layout()
plt.show()
The code above results to this:
https://i.stack.imgur.com/vbCnI.png
you need to change the subplot fig, axs = plt.subplots(nrows=1, ncols=2)
Your problem is not with the axis iteration but plotting with a continuous linestyle a set of points which are not x-axis ordered meaning that the line keeps going left and right, hence adds a lot of noise to the visualization.
Try:
fig, axs = plt.subplots(nrows=2, ncols=2)
for col, ax in zip(df.columns, axs.flatten()):
x_order = x.argsort()
ax.plot(x[x_order],y[x_order])
ax.set_title(col)
plt.subplots_adjust(wspace=.5, hspace=.5)
It seems to work in my environment when reproducing it on your sample
import matplotlib.pyplot as plt
import pandas as pd
s = """Month,Year,Region,Population
Jan,2008,Region.V,2.953926
Feb,2008,Region.V,2.183336
Jan,2009,Region.V,5.23598
Feb,2009,Region.V,3.719351
Jan,2008,Region.VI,3.232928
Feb,2008,Region.VI,2.297784
Jan,2009,Region.VI,6.231395
Feb,2009,Region.VI,7.493449"""
data = [l.split(',') for l in s.splitlines() if l]
df = pd.DataFrame(data[1:], columns=data[0])
df['Population'] = df['Population'].astype(float)
df["MonthYear"] = df["Month"].map(str) + " " + df["Year"].map(str)
df["MonthYear"] = pd.to_datetime(df["MonthYear"], format="%b %Y")
x = df["MonthYear"]
y = df['Population']
fig, axs = plt.subplots(nrows=2, ncols=2)
for col, ax in zip(df.columns, axs.flatten()):
x_order = x.argsort()
ax.plot(x[x_order],y[x_order])
ax.set_title(col)
plt.subplots_adjust(wspace=.5, hspace=.5)
fig.tight_layout()
plt.show()
which produces
Related
Using the code below,
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("population.csv")
df.head()
df["MonthYear"] = df["Month"].map(str) + " " + df["Year"].map(str)
df["MonthYear"] = pd.to_datetime(df["MonthYear"], format="%b %Y")
x = df["MonthYear"]
y = df["Population"]
fig, axs = plt.subplots(nrows=9, ncols=2, figsize = (9,19))
for col, ax in zip(df.columns, axs.flatten()):
ax.plot(x,y)
fig.tight_layout()
plt.show()
Can someone please help me try to figure out how to fix this? I'm doing it for days yet I can't figure it out.
Below:
create a datetime column and set it as index
split your dataset according to different possible values for "Region"
-> there is one subplot per Region
EDIT: with real dataset
EDIT: the author of the question has removed key informations from their question and deleted their comments. So to fully understand this answer:
the dataset is from here
in order to remove the last (empty) subplot: you should add fig.delaxes(axs.flat[-1])
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('denguecases.csv')
df['Date'] = pd.to_datetime(df.apply(lambda row: row.Month + ' ' + str(row.Year), axis=1))
df.set_index('Date', inplace=True)
fig, axs = plt.subplots(nrows=9, ncols=2, figsize = (9,19))
for region, ax in zip(df.Region.unique(), axs.flat):
ax.plot(df.query('Region == #region').Dengue_Cases)
ax.tick_params(axis='x', labelrotation = 45)
ax.set_title(region)
fig.tight_layout()
Try this instead:
for ax in axs.flatten():
ax.plot(x,y)
But this of course will plot the same plot in all the subplots. I am not sure if you have data for each subplot or you are expecting the same data for all plots.
Update:
Lets say you have n columns and you want to make n subplots
x = df["MonthYear"]
column_names = df.columns
n = len(column_names)
fig, axs = plt.subplots(nrows=9, ncols=2, figsize = (9,19))
for i in range(n):
y = df[column_names[i]]
axs.flatten()[i].plot(x,y)
Could someone give me a tip on how to do multiple Y axis plots?
This is some made up data below, how could I put Temperature its own Y axis, Pressure on its own Y axis, and then have both Value1 and Value2 on the same Y axis. I am trying to go for the same look and feel of this SO post answer. Thanks for any tips, I don't understand ax3 = ax.twinx() process, like as far as do I need to define an ax.twinx() for each separate Y axis plot I need?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
rows,cols = 8760,4
data = np.random.rand(rows,cols)
tidx = pd.date_range('2019-01-01', periods=rows, freq='H')
df = pd.DataFrame(data, columns=['Temperature','Value1','Pressure','Value2'], index=tidx)
# using subplots() function
fig, ax = plt.subplots(figsize=(25,8))
plt.title('Multy Y Plot')
ax2 = ax.twinx()
ax3 = ax.twinx()
ax4 = ax.twinx()
plot1, = ax.plot(df.index, df.Temperature)
plot2, = ax2.plot(df.index, df.Value1, color = 'r')
plot3, = ax3.plot(df.index, df.Pressure, color = 'g')
plot4, = ax4.plot(df.index, df.Value2, color = 'b')
ax.set_xlabel('Date')
ax.set_ylabel('Temperature')
ax2.set_ylabel('Value1')
ax3.set_ylabel('Pressure')
ax4.set_ylabel('Value2')
plt.legend([plot1,plot2,plot3,plot4],list(df.columns))
# defining display layout
plt.tight_layout()
# show plot
plt.show()
This will output everything jumbled up on the same side without separate Y axis for Pressure, Value1, and Value2.
You are adding 4 different plots in one, which is not helpful. I would recommend breaking it into 2 plots w/ shared x-axis "Date":
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
rows,cols = 8760,4
data = np.random.rand(rows,cols)
tidx = pd.date_range('2019-01-01', periods=rows, freq='H')
df = pd.DataFrame(data, columns=['Temperature','Value1','Pressure','Value2'], index=tidx)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(25,8))
plt.title('Multy Y Plot')
ax1b = ax1.twinx()
plot1a, = ax1.plot(df.index, df.Temperature)
plot1b, = ax1b.plot(df.index, df.Pressure, color='r')
ax1.set_ylabel('Temperature')
ax1b.set_ylabel('Pressure')
ax2b = ax2.twinx()
plot2a, = ax2.plot(df.index, df.Value1, color='k')
plot2b, = ax2b.plot(df.index, df.Value2, color='g')
ax2.set_xlabel('Date')
ax2.set_ylabel('Value1')
ax2b.set_ylabel('Value2')
plt.legend([plot1a, plot1b, plot2a, plot2b], df.columns)
# defining display layout
plt.tight_layout()
# show plot
plt.show()
Here I have added in the first plot (on the top) Temperature and Pressure and on the second plot (on the bottom) Value 1 and Value 2. Normally, we add in the same plot things that make sense to compare on the same x-axis. Pressure and Temperature is a valid combination that is why I combined those two together. But you can do as you wish.
This answer below uses mpatches is how to make the subplot of Value1 and Value2 on the same axis. The solution for this post has subplot for Value1 and Value2 on different axis. Thanks for the help #tzinie!
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
rows,cols = 8760,4
data = np.random.rand(rows,cols)
tidx = pd.date_range('2019-01-01', periods=rows, freq='H')
df = pd.DataFrame(data, columns=['Temperature','Value1','Pressure','Value2'], index=tidx)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(25,8))
plt.title('Multy Y Plot')
ax1b = ax1.twinx()
plot1a, = ax1.plot(df.index, df.Temperature, color='r') # red
plot1b, = ax1b.plot(df.index, df.Pressure, color='b') # blue
ax1.set_ylabel('Temperature')
ax1b.set_ylabel('Pressure')
ax2.plot(df.index, df.Value1, color='k') # black
ax2.plot(df.index, df.Value2, color='g') # green
ax2.set_xlabel('Date')
ax2.set_ylabel('Value1 & Value2')
red_patch = mpatches.Patch(color='red', label='Temperature')
blue_patch = mpatches.Patch(color='blue', label='Pressure')
green_patch = mpatches.Patch(color='green', label='Value2')
black_patch = mpatches.Patch(color='black', label='Value1')
plt.legend(handles=[red_patch,blue_patch,green_patch,black_patch])
# defining display layout
#plt.tight_layout()
# show plot
plt.show()
I'm trying to create a seaborn bar plot with three stacked figures that share an x axis and I want the x axis tick labels to be the product name, rotated by 90 degrees so they're legible.
I have managed to do this with a single figure plot using the following code:
ax = plt.subplots(1, 1, figsize=(15, 7), sharex=True)
#products_bar
products_bar = sns.barplot(x=products_all.index, y=products_all['Unique Purchases'], palette="tab10")
products_bar.set_xticklabels(products_all.index)
for item in products_bar.get_xticklabels():
item.set_rotation(90)
However, when I try to repeat this with the three figure (which splits the same data into three filters), the labels stay stubbornly as numbers from the dataframe instead. Here is the code -
f, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(15, 10), sharex=True)
products_bar.set_xticklabels(organic.index)
for item in products_bar.get_xticklabels():
item.set_rotation(45)
products_bar = sns.barplot(x=organic.index, y=organic['Unique Purchases'], palette="tab10", ax=ax1)
products_bar = sns.barplot(x=paid.index, y=paid['Unique Purchases'], palette="tab10", ax=ax2)
products_bar = sns.barplot(x=social.index, y=social['Unique Purchases'], palette="tab10", ax=ax3)
I'm not entirely sure what keywords to search to find the answer.
Since you used sharex=True, you just change the axis ticks on the last plot:
import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
idx = ["day"+str(i) for i in range(5)]
organic = pd.DataFrame({"Unique Purchases":np.random.randint(1,10,5)},index=idx)
paid = pd.DataFrame({"Unique Purchases":np.random.randint(1,10,5)},index=idx)
social = pd.DataFrame({"Unique Purchases":np.random.randint(1,10,5)},index=idx)
f, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(15, 10), sharex=True)
ax1 = sns.barplot(x=organic.index, y=organic['Unique Purchases'], palette="tab10", ax=ax1)
ax2 = sns.barplot(x=paid.index, y=paid['Unique Purchases'], palette="tab10", ax=ax2)
ax3 = sns.barplot(x=social.index, y=social['Unique Purchases'], palette="tab10", ax=ax3)
ax3.tick_params(labelrotation=45)
I have the following script for generating a figure with two subplots: one line plot, and one bar plot.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
plt.close('all')
np.random.seed(42)
n = 1000
idx = pd.date_range(end='2020-02-27', periods=n)
df = pd.Series(np.random.randint(-5, 5, n),
index=idx)
curve = df.cumsum()
bars = df.resample('M').sum()
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
curve.plot(ax=ax1)
bars.plot(kind='bar', ax=ax2)
fig.set_tight_layout(True)
I would like to share the x axis between the two subplots, however the command ax2 = fig.add_subplot(212, sharex=ax1) will result in an empty graph for the line plot like the following figure.
Here is my version based on Matplotlib (without pandas api for plotting), may be it would be helpful.
I explicitly set the width of bars.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
%matplotlib inline
plt.close('all')
np.random.seed(42)
n = 1000
idx = pd.date_range(end='2020-02-27', periods=n)
df = pd.Series(np.random.randint(-5, 5, n), index=idx)
curve = df.cumsum()
bars = df.resample('M').sum()
#fig = plt.figure()
#ax1 = fig.add_subplot(211)
#ax2 = fig.add_subplot(212)
#curve.plot(ax=ax1)
#bars.plot(kind='bar', ax=ax2)
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, gridspec_kw={'hspace': 0})
ax1.plot(curve.index, curve.values)
ax2.bar(bars.index, bars.values, width = (bars.index[0] - bars.index[1])/2)
fig.set_tight_layout(True)
_ = plt.xticks(bars.index, bars.index, rotation=90)
How would I go about formatting the below pie chart subplots so that there is more white-space between the fig title and subplot titles. Ideally the subplot titles would also be in closer vicinity to the actual pie chart itself.
I can't seem to find anything in the docs which might enable this, but I'm new to matplotlib.
import matplotlib.pyplot as plt
import pandas as pd
from pandas import DataFrame, Series
m = {"Men" : {"Yes": 2, "No": 8}}
w = {"Women": {"Yes": 3, "No": 7}}
data = {**m, **w}
df = DataFrame(data)
fig, axes = plt.subplots(1, len(df.columns))
fig.suptitle("Would you prefer to work from home?", fontsize=18)
logging.debug("fig.axes: {}".format(fig.axes))
for i, ax in enumerate(fig.axes):
col = df.ix[:, i]
ax = fig.axes[i]
pcnt_col = col / col.sum() * 100
ax.set_title("{} (n={})".format(pcnt_col.name, col.sum()))
ax.pie(pcnt_col.values, labels=pcnt_col.index,
autopct="%1.1f%%", startangle=90)
ax.axis("equal")
plt.legend(loc="lower right", title="Answer", fancybox=True,
ncol=1, shadow=True)
plt.show()
Use subplots_adjust to separate the two
plt.subplots_adjust(top=0.75)
import matplotlib.pyplot as plt
import pandas as pd
from pandas import DataFrame, Series
m = {"Men" : {"Yes": 2, "No": 8}}
w = {"Women": {"Yes": 3, "No": 7}}
data = {**m, **w}
df = DataFrame(data)
fig, axes = plt.subplots(1, len(df.columns))
fig.suptitle("Would you prefer to work from home?", fontsize=18)
logging.debug("fig.axes: {}".format(fig.axes))
for i, ax in enumerate(fig.axes):
col = df.ix[:, i]
ax = fig.axes[i]
pcnt_col = col / col.sum() * 100
ax.set_title("{} (n={})".format(pcnt_col.name, col.sum()))
ax.pie(pcnt_col.values, labels=pcnt_col.index,
autopct="%1.1f%%", startangle=90)
ax.axis("equal")
plt.legend(loc="lower right", title="Answer", fancybox=True,
ncol=1, shadow=True)
plt.subplots_adjust(top=0.55)
plt.show()