Elena Greg
Elena Greg

Reputation: 1165

How to set markers with errorbars in different colours?

How to:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D  # for legend handle

fig, ax = plt.subplots(figsize = (10,10))

times = [1, 2, 3, 4, 5]
rvs = [2, 4, 2, 4, 7]
sigma = [0.564, 0.6, 0.8, 0.8, 0.4]
rv_telescopes = ['A', 'B', 'A', 'C', 'C']

d = {'rv_times': times, 'rv_rvs': rvs, 'rv_sigma': sigma, 'rv_telescopes': rv_telescopes }
df = pd.DataFrame(data=d)

colors = {'A':'#008f00', 'B':'#e36500', 'C':'red'}

plt.errorbar(df['rv_times'], df['rv_rvs'], df['rv_sigma'], marker = '_', ecolor = df['rv_telescopes'].map(colors), color = df['rv_telescopes'].map(colors), zorder = 1, ms = 30)


handles = [Line2D([0], [0], marker='_', color='w', markerfacecolor=v, label=k, markersize=10) for k, v in colors.items()]

ax.legend(handles=handles, loc='upper left', ncol = 2, fontsize=14)

plt.show()

plot

After edit

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D  # for legend handle
import pandas as pd
import numpy as np

times = [1, 2, 3, 4, 5]
rvs = [2, 4, 2, 4, 7]
sigma = [0.564, 0.6, 0.8, 0.8, 0.4]
rv_telescopes = ['A', 'B', 'A', 'C', 'C']

d = {'rv_times': times, 'rv_rvs': rvs, 'rv_sigma': sigma, 'rv_telescopes': rv_telescopes}
df = pd.DataFrame(data=d)
colors = {'A': '#008f00', 'B': '#e36500', 'C': 'red'}

fig, ax = plt.subplots(figsize=(10, 10))
ax.errorbar(df['rv_times'], df['rv_rvs'], df['rv_sigma'], color='none', ecolor=df['rv_telescopes'].map(colors) ,linewidth=1)
ax.scatter(df['rv_times'], df['rv_rvs'], marker='_', linewidth=3, color=df['rv_telescopes'].map(colors), s=1000)

for rv_teles in np.unique(df['rv_telescopes']):
     color = colors[rv_teles]
     df1 = df[df['rv_telescopes'] == rv_teles]  # filter out rows corresponding to df['rv_telescopes']
     ax.errorbar(df1['rv_times'], df1['rv_rvs'], df1['rv_sigma'],
                 color=color, ls='', marker='_', ms=30, linewidth=3, label=rv_teles)
ax.legend(loc='upper left', ncol=1, fontsize=14)
plt.show()

enter image description here

Upvotes: 0

Views: 3263

Answers (1)

JohanC
JohanC

Reputation: 80449

plt.errorbar() works very similar to plt.plot() with extra parameters. As such, it primarily draws a line graph, using a single color. The error bars can be given individual colors via the ecolor= parameter. The markers, however, get the same color as the line graph. The line graph can be suppressed via an empty linestyle. On top of that, plt.scatter() can draw markers with individual colors.

In order not the mix the 'object-oriented' with the 'functional interface', the following example code uses ax.errorbar() and ax.scatter().

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D  # for legend handle
import pandas as pd
import numpy as np

times = [1, 2, 3, 4, 5]
rvs = [2, 4, 2, 4, 7]
sigma = [0.564, 0.6, 0.8, 0.8, 0.4]
rv_telescopes = ['A', 'B', 'A', 'C', 'C']

d = {'rv_times': times, 'rv_rvs': rvs, 'rv_sigma': sigma, 'rv_telescopes': rv_telescopes}
df = pd.DataFrame(data=d)
colors = {'A': '#008f00', 'B': '#e36500', 'C': 'red'}

fig, ax = plt.subplots(figsize=(10, 10))
ax.errorbar(df['rv_times'], df['rv_rvs'], df['rv_sigma'], color='none', ecolor=df['rv_telescopes'].map(colors))
ax.scatter(df['rv_times'], df['rv_rvs'], marker='_', color=df['rv_telescopes'].map(colors), s=100)

handles = [Line2D([0], [0], linestyle='', marker='_', color=v, label=k, markersize=10) for k, v in colors.items()]
ax.legend(handles=handles, loc='upper left', ncol=1, fontsize=14)
plt.show()

error bars with individual colors

A far easier approach would be to call ax.errorbar() multiple times, once for each color. This would automatically create appropriate legend handles:

for rv_teles in np.unique(df['rv_telescopes']):
     color = colors[rv_teles]
     df1 = df[df['rv_telescopes'] == rv_teles]  # filter out rows corresponding to df['rv_telescopes']
     ax.errorbar(df1['rv_times'], df1['rv_rvs'], df1['rv_sigma'],
                 color=color, ls='', marker='_', ms=30, label=rv_teles)
ax.legend(loc='upper left', ncol=1, fontsize=14)
plt.show()

calling ax.errorbar once for each color

Upvotes: 1

Related Questions