Reputation: 1998
I have a dataframe that looks like this. I need a subplot for each unique Item (book, Table and Chair). The plots should be sorted by Year (Year is also the x-axis). I need to make use of twiny to have Price on the left and Quantity plotted on the right of each subplot.
I can do this manually for each Item by creating a individual dataframe. So I created a dataframe for Book, then sorted by Year and set Year as index. then create the plot with secondary_y. But obviously this is long winded. Is there a way to do this from the original dataframe without all the manual processing?
Item Year Price Quantity
0 Book 2000 $2 50
1 Table 2000 $33 44
2 Chair 2000 $21 31
3 Book 2001 $3 77
4 Table 2001 $20 500
5 Chair 2001 $2 50
6 Book 2002 $36 7
7 Table 2002 $200 50
8 Chair 2002 $44 5
Upvotes: 0
Views: 1910
Reputation: 1083
You may find seaborn's factorplot very useful for this: https://seaborn.pydata.org/generated/seaborn.factorplot.html
It handles plotting categorised data like yours, saving you the effort of grouping and looping. There are lots of examples at the above link, but hopefully this is close to what you want:
%matplotlib inline
import seaborn as sns
import pandas as pd
data = pd.DataFrame({
'Item': ['Book', 'Table', 'Chair'] * 3,
'Year': [2000] * 3 + [2001] * 3 + [2002] * 3,
'Price': [2, 33, 21, 3, 20, 2, 36, 200, 44],
'Quantity': [50, 44, 31, 77, 500, 50, 7, 50, 5],
})
g = sns.factorplot(data=data, x='Year', y='Price',
col='Item', kind='bar', sharey=False)
If you want to plot both price and quantity (using a secondary y axis), you can use a custom FacetGrid object with map_dataframe. This doesn't seem to play so well with seaborn though; labels, legend, etc need to be added afterwards. I think the preference for their categorical plotting functions is to create more plots rather than use secondary axes (i.e. a second row of plots for quantity).
def bar_plot(data, **kwargs):
''' Called with each subset of data by 'Item' '''
ax = plt.gca()
data[['Year', 'Price', 'Quantity']].plot(
x='Year', kind='bar', ax=ax, secondary_y='Quantity')
g = sns.FacetGrid(data=data, col='Item', sharey=False)
g.map_dataframe(bar_plot)
Upvotes: 2
Reputation: 11887
Not sure what you mean here, but maybe your can use groupby()
and then traverse the groups?
Here's a simple example (using pyplot)
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
dicts = []
dicts.append({'item':'book','year':2000,'price':2, 'quantity':50})
dicts.append({'item':'table','year':2000,'price':33, 'quantity':44})
dicts.append({'item':'chair','year':2000,'price':21, 'quantity':31})
dicts.append({'item':'book','year':2001,'price':3, 'quantity':50})
dicts.append({'item':'table','year':2001,'price':20, 'quantity':44})
dicts.append({'item':'chair','year':2001,'price':2, 'quantity':31})
dicts.append({'item':'book','year':2002,'price':36, 'quantity':7})
dicts.append({'item':'table','year':2002,'price':200, 'quantity':50})
dicts.append({'item':'chair','year':2002,'price':44, 'quantity':5})
df = pd.DataFrame.from_records(dicts)
grouped = df.groupby('item')
fig, axes = plt.subplots(1,3,sharey=True)
fig.set_size_inches(15,4)
for i,group_key in enumerate(list(grouped.groups.keys())):
grouped.get_group(group_key).set_index('year').plot(kind='bar',ax = axes[i])
axes[i].set_title(group_key,fontsize=15)
Upvotes: 1