SHV_la
SHV_la

Reputation: 987

Matplotlib: bring one set of scatter plot data to front

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:

enter image description here

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

Answers (2)

SpghttCd
SpghttCd

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()    

enter image description here


...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

anotherone
anotherone

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

Related Questions