2

Maybe I am too used to R's wonderful ggplot-idiom when doing faceted charts (it takes numeric and string variables without protest) but the ideal way outside ggplot has certainly eluded me for some time getting to know the matplotlib world.

I am typically faceting a lot of bar charts by several dimensions, and have recently found the eminent seaborn library building on matplotlib which has an easy faceting interface.

Bar plots typically require a numeric vector (as opposed to a categorical string vector) for the x variable--here first some mock data and a basic plot:

import pandas as pd
import numpy as np
import seaborn as sns
N = 100

## generate toy data
ind = np.random.choice(['retail','construction','information'], N)
cty = np.random.choice(['cooltown','mountain pines'], N)
age = np.random.choice(['young','old'], N)
jobs = np.random.randint(low=1,high=250,size=N)

## prep data frame
df_city = pd.DataFrame({'industry':ind,'city':cty,'jobs':jobs,'age':age})
df_city_grouped = df_city.groupby(['city','industry','age']).sum()
df_city_grouped.unstack().plot(kind='bar',stacked=True,figsize=(9, 6),title='Jobs by city, industry, age group')

Which yields this plot. This dataframe method of plot can use indices to plot behind the scenes: matplotlib plot

Now, onto seaborn which has a nice faceting interface. First I flatten the multiindices so I have columns instead (I think this is required for the API).

df_city_grouped.reset_index(inplace=True)
df_city_grouped.head()

+----------+--------------+-------+------+
| city     | industry     | age   | jobs |
+----------+--------------+-------+------+
| cooltown | construction | old   | 563  |
+----------+--------------+-------+------+
| cooltown | construction | young | 1337 |
+----------+--------------+-------+------+
| cooltown | information  | old   | 1234 |
+----------+--------------+-------+------+
| cooltown | information  | young | 1402 |
+----------+--------------+-------+------+
| cooltown | retail       | old   | 1035 |
+----------+--------------+-------+------+

Calling this gives me the error TypeError: cannot concatenate 'str' and 'float' objects.

g = sns.FacetGrid(df_city_grouped, col="industry", row="city", margin_titles=True)
g.map(plt.bar, "age","jobs", color="darkred", lw=0)

However, I can hack it and turn one of the categorical variables back to a number:

mapping = {
'young': 1,
'middle':2,
'old':3}

df_city_grouped['age2']=df_city_grouped.age.map(mapping) 
g = sns.FacetGrid(df_city_grouped, col="industry", row="city", margin_titles=True)
g.map(plt.bar, "age2","jobs", color="darkred", lw=0)

Which yields the approximate result (but with decimals on x). seaborn plot with numeric axis So my question is--what is the best way to deal with categorical axes in the faceting example? (Incidentally noting that

f, (ax) = plt.subplots()
sns.barplot(df_city_grouped.industry, df_city_grouped.jobs, ax=ax, ci=None)

does work with categorical labels. outside the faceting idiom.)

2
  • By the way you could also have mapped sns.barplot on the FacetGrid. There's no reason to with factorplot, but you can pass any function to FacetGrid.map it doesn't have to be in the plt namespace. Commented Oct 4, 2014 at 0:51
  • cool stuff. The API is pretty neat. Commented Oct 4, 2014 at 2:46

1 Answer 1

4

Use sns.factorplot with kind="bar". See the docs for more information, but here's an example with your data:

sns.factorplot("age", "jobs", col="industry", row="city", data=df_city,
               margin_titles=True, size=3, aspect=.8, palette=["darkred"])

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Hot damn, was just googling to try to figure out how to best visualize a potential three-way interaction. This is fantastic! Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.