Reputation: 987
I have a series of subplots with red and blue markers, I am most interested in the red markers so want to bring them to the front of the plot:
The data structure is like this:
SzT Pcp Pcp_3day Pcp_7day Pcp_10day Pcp_14day Pcp_21day Pcp_28day
date
2017-12-04 0.0 8.382 19.304 21.082 40.132 40.132 42.418 71.374
2017-12-05 0.0 12.192 20.574 33.020 42.164 52.324 52.578 81.534
2017-12-06 0.0 1.016 21.590 33.020 34.290 53.340 53.594 82.550
2017-12-07 0.0 12.700 25.908 45.466 46.990 66.040 66.040 95.250
2017-12-08 0.0 5.080 18.796 50.292 51.816 71.120 71.120 88.900
The colours are determined by the value of 'SzT' that each data point belongs to, which is either 1 or 0 (though in the above only '0' is shown). I constructed this with the code below:
colors = {0 : 'b',
1 : 'r'}
fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(111)
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
c = [colors[i] for i in RGDFT8mm['SzT']]
m = [marker[i] for i in RGDFT8mm['SzT']]
ax1.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_3day'], c=c)
ax2.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_7day'], c=c)
ax3.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_14day'], c=c)
ax4.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_28day'], c=c)
ax.set_title('Daily Rainfall vs antecedent rainfall from Rain Gauges 2001-2017')
ax.set_xlabel('Daily Rainfall (mm)')
ax.set_ylabel('Antecedent rainfall (mm)')
ax.set_yticklabels([])
ax.set_xticklabels([])
ax1.set_title('3 Day')
ax2.set_title('7 Day')
ax3.set_title('14 Day')
ax4.set_title('28 Day')
I can't find any information that is helpful elsewhere. Any ideas out there?
Thanks!
UPDATE: Apologies for the poor original structure, I have added the structure of the data above FYI.
Upvotes: 6
Views: 11621
Reputation: 10890
At first it's quite difficult to say sth concrete without knowing the structure of your data in the dataframe, so please consider posting e.g. RGDFT8mm.head()
That said, I see at least from your code that you have mixed red and blue data in one dataframe without grouping (=separating) it before scatter plotting. Therefore one scatter command contains both colors making it impossible to get one color in the foreground.
If you restructure so that each scatter command only plots a single color, every scatter will be plotted on top of the previous one, and besides that, you can use the zorder
kwarg to define the layer of each dataset at your own will.
For grouping you can use sth like RGDFT8mm.groupby('SzT')
- however, to give useful hints from here on I would rather wait to know your dataframe structure exactly.
But my first guess would be:
for grpname, grpdata in RGDFT8mm.groupby('SzT'):
ax1.scatter(grpdata['Pcp'], grpdata['Pcp_3day'])
ax2.scatter(grpdata['Pcp'], grpdata['Pcp_7day'])
ax3.scatter(grpdata['Pcp'], grpdata['Pcp_14day'])
ax4.scatter(grpdata['Pcp'], grpdata['Pcp_28day'])
Edit Examples for clarification
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data = lambda n: np.random.lognormal(sigma=.5, size=n)
np.random.seed(42)
df = pd.DataFrame({'Pcp': data(500), 'Pcp_3day': data(500), 'SzT': (np.random.random(500)>.9).astype(int)})
print(df.head())
fig, axs = plt.subplots(2, 2, sharex=True, sharey=True)
szt_hi = df.SzT > 0
axs[0, 0].set_title('plot red before blue')
axs[0, 0].scatter(df.loc[szt_hi, 'Pcp'], df.loc[szt_hi, 'Pcp_3day'], c='r', label='SzT=1')
axs[0, 0].scatter(df.loc[~szt_hi, 'Pcp'], df.loc[~szt_hi, 'Pcp_3day'], c='b', label='SzT=0')
axs[0, 0].legend()
axs[0, 1].set_title('plot blue before red')
axs[0, 1].scatter(df.loc[~szt_hi, 'Pcp'], df.loc[~szt_hi, 'Pcp_3day'], c='b', label='SzT=0')
axs[0, 1].scatter(df.loc[szt_hi, 'Pcp'], df.loc[szt_hi, 'Pcp_3day'], c='r', label='SzT=1')
axs[0, 1].legend()
colors = {0 : 'b', 1 : 'r'}
layer = {0: 1, 1: 0}
axs[1, 0].set_title('plot by looping over groups\n(leading to blue first here)')
for i, (n, g) in enumerate(df.groupby('SzT')):
axs[1, 0].scatter(g.Pcp, g.Pcp_3day, c=colors[i], label='SzT={}'.format(n))
axs[1, 0].legend()
axs[1, 1].set_title('plot by looping over groups \n(leading to blue first here)\nwith manipulating zorder')
for i, (n, g) in enumerate(df.groupby('SzT')):
axs[1, 1].scatter(g.Pcp, g.Pcp_3day, c=colors[i], zorder=layer[i], label='SzT={}'.format(n))
axs[1, 1].legend()
plt.show()
...to print legend
less times one could loop over all axes like
for a in axs.flatten():
a.legend()
after plotting all subplots.
However, in your case in contrast to my examples, your legends would all be the same, so that one legend for the whole figure would be better. For this just use
fig.legend()
modifiable with the same parameters like axis legends.
Upvotes: 2
Reputation: 795
Just set the alpha of the scatter points. Something like the following code. Of course, you can play with the alpha values.
colors = {0 : (0, 0, 1, 0.3),
1 : (1, 0, 0, 1.0)}
fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(111)
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
c = [colors[i] for i in RGDFT8mm['SzT']]
m = [marker[i] for i in RGDFT8mm['SzT']]
ax1.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_3day'], c=c)
ax2.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_7day'], c=c)
ax3.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_14day'], c=c)
ax4.scatter(RGDFT8mm['Pcp'], RGDFT8mm['Pcp_28day'], c=c)
ax.set_title('Daily Rainfall vs antecedent rainfall from Rain Gauges 2001-2017')
ax.set_xlabel('Daily Rainfall (mm)')
ax.set_ylabel('Antecedent rainfall (mm)')
ax.set_yticklabels([])
ax.set_xticklabels([])
ax1.set_title('3 Day')
ax2.set_title('7 Day')
ax3.set_title('14 Day')
ax4.set_title('28 Day')
Also just a suggestion: use plt.subplots() and zip when plotting multiple plots. I find that neat and helpful. Check this
Upvotes: 1