0

I try to generate two scatterplots (side by side), and the code for that in matplotlib is quite straightforward and self-explanatory. however, my dataset is somehow complex, meaning for each x value, there are 2-3 corresponding y values, so I created an array for that.

here is the code to generate one plot:

import matplotlib.pyplot as plt
import numpy as np


plt.close('all')


data = np.array([
    [-2, 22.8],
    [-2, 0.3],
    [-2, 3.1],
    [-1, -1.7],
    [-1, 4.8],
    [-1, -0.7],
    [ 0, -2.6],
    [ 0, -0.03],
    [ 1, -5.7],
    [ 1, -1.5],
    [ 1, -3.9],
    [ 2, -21.5],
    [ 2, -7.7],
]) 

custom_annotations = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]

plt.scatter(data[:,0], data[:,1], marker='o', c=data[:,1], edgecolors='black', linewidths=1, alpha=0.75)

# plt.colorbar(orientation='horizontal')
plt.xlabel(r'$\Delta q$')
plt.ylabel(r'$\delta  V_{0.5}$  Apo wild-type mHCN2 (mV)')

plt.axvline(0, c=(.5, .5, .5), ls= '--')
plt.axhline(0, c=(.5, .5, .5), ls= '--')



for i, txt in enumerate(custom_annotations):
    plt.annotate(txt, (data[i,0], data[i,1]))

when i attempted to generate a panel of two, i intuitively defined one as data1 and the other as data2 and proceeded with the matplotlib code, here is how:

import matplotlib.pyplot as plt
import numpy as np



data1 = np.array([
    [-2, 22.8],
    [-2, 19.6],
    [-2, 0.3],
    [-1, 8.9],
    [-1, 13.7],
    [-1, 14.7,],
    [ 0, 1.9],
    [ 0, -1.8],
    [ 1, -3],
    [ 1, -5.9],
    [ 1, -13.4],
    [ 2, -5.7],
    [ 2, -6.8],
]) 

data2 =  np.array([
    [-2, 22.8],
    [-2, 0.3],
    [-2, 3.1],
    [-1, -1.7],
    [-1, 4.8],
    [-1, -0.7],
    [ 0, -2.6],
    [ 0, -0.03],
    [ 1, -5.7],
    [ 1, -1.5],
    [ 1, -3.9],
    [ 2, -21.5],
    [ 2, -7.7],
]) 


custom_annotations = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]


ax1.scatter(data1[:,0], data1[:,1])
ax2.scatter(data2[:,0], data2[:,1])

ax1.set_title('Experimental Apo mHCN2 Channel')
ax1.set_xlabel(r'$\Delta q$')
ax1.set_ylabel(r'$\delta  V_{0.5}$  Apo wild-type mHCN2 (mV)')

ax2.set_title('Electrostatic Potential Calculations - Holo mHCN2 Channel')
ax2.set_xlabel(r'$\Delta q$')
ax2.set_ylabel(r'$\delta  V_{0.5}$  Apo wild-type mHCN2 (mV)')

plt.axvline(0, c=(.5, .5, .5), ls= '--')
plt.axhline(0, c=(.5, .5, .5), ls= '--')



for i, txt in enumerate(custom_annotations):
    plt.annotate(txt, (data1[i,0], data1[i,1]))
    plt.annotate(txt, (data2[i,0], data2[i,1]))


plt.show()

this generated an empty plot, so there should be something fatal that went wrong.

in addition, as the values on the y-axis differ considerably between the two datasets, i end up with a different y-axis spacing, is there a way to fix that?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
sphero
  • 37
  • 9
  • You're (second) code is not complete. Where and how do you define `ax1` and `ax2`? – Szala Apr 22 '22 at 12:21
  • 1
    Add this to the second code. `fig, (ax1,ax2) = plt.subplots(1,2, figsize=(12,9))` – r-beginners Apr 22 '22 at 12:27
  • @r-beginners not directly related to the question. i copied OPs code, added your line at the beginning. Now I guess he also wants the annotation and the vertical and horizontal line in both plots. doing this in a loop like this: `for ax in (ax1,ax2): #do stuff` works fine. Considered I don't want to list them all by hand I searched for a more general approach. `ax1` is an `AxesSubplot` Object. Is there a way to just call all the defined ax1,...,axn together, e.g. `for ax in AxesSubplots:...` ? – Rabinzel Apr 22 '22 at 12:46
  • @Rabinzel To loop through the processing common to the two graphs, the code would be as follows. `fig, axs = plt.subplots(1,2, figsize=(12, 9));for ax in axs.faltten(): ax.axvline(..);ax.axhline(..);` – r-beginners Apr 22 '22 at 13:02
  • @beginners i added that line and the output was just a panel of two plots without any data inside, however the label axes are there... how can i get my points plotted in a scater fashion? – sphero Apr 22 '22 at 13:04
  • @KhalidHelmy i ran your code with the added line of code of r-beginner and it worked for me – Rabinzel Apr 22 '22 at 13:37
  • @r-beginners ok, so I define them as `axs` in the beginning, but than I need to unpack them after like `ax1, ax2 = axs` right ? – Rabinzel Apr 22 '22 at 13:41
  • @Rabinzel could you share the full code? maybe I am missing something... – sphero Apr 22 '22 at 13:52
  • @Rabinzel The axs contains subplot objects as arrays, which are processed sequentially in a loop. – r-beginners Apr 22 '22 at 13:54
  • thanks to both of you! is there a way to unify the y-axis spacing? – sphero Apr 22 '22 at 14:21
  • i will add the line of code in the answer below. When defining the subplots there is an argument `sharey`, you can set that to `row` and your plots share the same y-axis. – Rabinzel Apr 22 '22 at 14:25
  • if you don't want to share them, you can also have a look at that [answer](https://stackoverflow.com/a/56646584/15521392) . You just need to change the range of `xlim` and `ylim` and change the argument in `plt.setp` to `axs` since thats the name with who we defined the subplots – Rabinzel Apr 22 '22 at 14:34
  • 1
    @Rabinzel the suggested answer worked quite well, thank you! – sphero Apr 22 '22 at 14:44

1 Answers1

2
import matplotlib.pyplot as plt
import numpy as np

data1 = np.array([
    [-2, 22.8],
    [-2, 19.6],
    [-2, 0.3],
    [-1, 8.9],
    [-1, 13.7],
    [-1, 14.7,],
    [ 0, 1.9],
    [ 0, -1.8],
    [ 1, -3],
    [ 1, -5.9],
    [ 1, -13.4],
    [ 2, -5.7],
    [ 2, -6.8],
]) 

data2 =  np.array([
    [-2, 22.8],
    [-2, 0.3],
    [-2, 3.1],
    [-1, -1.7],
    [-1, 4.8],
    [-1, -0.7],
    [ 0, -2.6],
    [ 0, -0.03],
    [ 1, -5.7],
    [ 1, -1.5],
    [ 1, -3.9],
    [ 2, -21.5],
    [ 2, -7.7],
]) 

custom_annotations = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]

fig, axs = plt.subplots(1,2, figsize=(12,9), sharey='row')
ax1,ax2 = axs

ax1.scatter(data1[:,0], data1[:,1])
ax2.scatter(data2[:,0], data2[:,1])

ax1.set_title('Experimental Apo mHCN2 Channel')
ax1.set_xlabel(r'$\Delta q$')
ax1.set_ylabel(r'$\delta  V_{0.5}$  Apo wild-type mHCN2 (mV)')

ax2.set_title('Electrostatic Potential Calculations - Holo mHCN2 Channel')
ax2.set_xlabel(r'$\Delta q$')

for ax in axs:
    ax.axvline(0, c=(.5, .5, .5), ls= '--')
    ax.axhline(0, c=(.5, .5, .5), ls= '--')

for i, txt in enumerate(custom_annotations):
    ax1.annotate(txt, (data1[i,0], data1[i,1]))
    ax2.annotate(txt, (data2[i,0], data2[i,1]))
    
plt.show()

enter image description here

Rabinzel
  • 7,757
  • 3
  • 10
  • 30