title: Matplotlib / Seaborn barplot--strings in x axis
body: <p>Maybe I am too used to <code>R's</code> wonderful <code>ggplot</code>-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.</p>
  
  <p>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.</p>
  
  <p>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:</p>
  
  <pre><code>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')
  </code></pre>
  
  <p>Which yields this plot. This dataframe method of plot can use indices to plot behind the scenes:
  <img src="https://i.stack.imgur.com/tQFMR.png" alt="matplotlib plot"></p>
  
  <p>Now, onto <strong>seaborn</strong> which has a nice faceting interface.
  First I flatten the multiindices so I have columns instead (I think this is required for the API).</p>
  
  <pre><code>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 |
  +----------+--------------+-------+------+
  </code></pre>
  
  <p>Calling this gives me the error <code>TypeError: cannot concatenate 'str' and 'float' objects</code>.</p>
  
  <pre><code>g = sns.FacetGrid(df_city_grouped, col="industry", row="city", margin_titles=True)
  g.map(plt.bar, "age","jobs", color="darkred", lw=0)
  </code></pre>
  
  <p>However, I can hack it and turn one of the categorical variables back to a number:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>Which yields the approximate result (but with decimals on x).
  <img src="https://i.stack.imgur.com/7UN7S.png" alt="seaborn plot with numeric axis">
  So <strong>my question</strong> is--what is the best way to deal with categorical axes in the faceting example? (Incidentally noting that </p>
  
  <pre><code>f, (ax) = plt.subplots()
  sns.barplot(df_city_grouped.industry, df_city_grouped.jobs, ax=ax, ci=None)
  </code></pre>
  
  <p>does work with categorical labels. outside the faceting idiom.)</p>