2

I'm trying to use swarmplot with a single axis, but where the data points are colored differently based on a category.

Here is an example:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
    
data = [
    (12, 50, 'Free', 'W'),
    (14, 1650, 'Free', 'W'),
    (17, 500, 'Free', 'W'),
    (17, 200, 'Free', 'W'),
    (28, 100, 'Free', 'W'),
    (33, 400, 'IM', 'W'),
    (36, 200, 'Fly', 'W'),
    (48, 100, 'Fly', 'W'),
    (52, 200, 'IM', 'W'),
    (54, 200, 'Back', 'W'),
    (54, 200, 'Breast', 'W'),
    (100, 100, 'Breast', 'W'),
    (100, 100, 'Back', 'W')
]


rank, dist, stroke, gender = zip(*data)
frame = pd.DataFrame(data={'rank': rank, 'distance': dist,
    'stroke': stroke, 'gender': gender})

# this one works, except I don't want to spread the points out
# along the y-axis
# sns.catplot(x='rank', y='distance', hue='stroke', kind='swarm', data=frame)

sns.catplot(x='rank', kind='swarm', data=frame, hue='stroke')
plt.show()

The above fails with:

Traceback (most recent call last):
  File "test.py", line 31, in <module>
    sns.catplot(x='rank', kind='swarm', data=frame, hue='stroke')
  File "<...>/python3.6/site-packages/seaborn/categorical.py", line 3765, in catplot
    hue_order = list(map(utils.to_utf8, hue_order))
TypeError: 'NoneType' object is not iterable

Is there a way to get this to work without providing a y field?

Marcus Campbell
  • 2,746
  • 4
  • 22
  • 36
Barry
  • 286,269
  • 29
  • 621
  • 977

2 Answers2

3

hue= has to be nested under x/y so you cannot use it without both being provided.

It seems to me the correct way to display your data would be to use y='stroke'

sns.catplot(x='rank', y='stroke', kind='swarm', data=frame)

enter image description here

If you really want all the points to be aligned on a single line, then you can fake a common category to use for all the points and to pass that to y=. After that, it's just a matter of cosmetics to get the labels that are appropriate:

frame.loc[:,'dummy'] = 'dummy'

g = sns.catplot(x='rank', y='dummy', hue='stroke', kind='swarm', data=frame)
g.axes[0,0].set_ylabel("")
g.axes[0,0].set_yticklabels([""])

enter image description here

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
0

Since you don't want the y-axis to show, you can use sns.countplot() instead of sns.catplot().

Papershine
  • 4,995
  • 2
  • 24
  • 48
  • 1
    Could you please use proper grammar and spelling on this site? It helps others read a bit quicker. Thanks! – Rojo Jul 25 '20 at 22:22