2

I need to export 6 violin subplots made using seaborn through python onto a single page PDF. They need to be formatted into 3 rows x 2 columns. Right now my code is generating a single page PDF with 6 empty plots and in the console this grid of empty plots appears as well as my 6 individual violin subplots (which I need to appear in the 3x2 grid format). I need to fix my code to make the violin plots export correctly as a PDF.

data = pd.read_csv(os.path.join(input_folder, input_file))


x = "Subregion"
hue = "Mutation"
col = "Subregion"
kind = "violin"
data = M1
title_name = "M1"



fig, ([ax1, ax2], [ax3, ax4], [ax5, ax6]) = plt.subplots(nrows=3, ncols=2,figsize = (6,6))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
ax1 = sns.catplot(x = x, y = "Area_mm", hue = hue, col = None, kind = kind, data = data, legend = False)
ax1.set_ylabels("Area (mm^2)")
ax2 = sns.catplot(x = x, y = "DAPI_count", hue = hue, col = None, kind = kind, data = data, legend = False)
ax2.set_ylabels("DAPI Cell Count")
ax3 = sns.catplot(x = x, y = "SST_count", hue = hue, col = None, kind = kind, data = data, legend = False)
ax3.set_ylabels("SST Cell Count")
ax4 = sns.catplot(x = x, y = "DAPI_per_area", hue = hue, col = None, kind = kind, data = data, legend = False)
ax4.set_ylabels("DAPI Cell Density (DAPI/mm^2)")
ax5 = sns.catplot(x = x, y = "SST_per_area", hue = hue, col = None, kind = kind, data = data, legend = False)
ax5.set_ylabels("SST Cell Density (SST/mm^2)")
ax6 = sns.catplot(x = x, y = "SST_per_DAPI", hue = hue, col = None, kind = kind, data = data, legend = False)
ax6.set_ylabels("SST Cell Density (% SST/DAPI cells)")

fig.savefig(os.path.join(output_folder, title_name + '.pdf'))
StupidWolf
  • 45,075
  • 17
  • 40
  • 72
GKC2024
  • 21
  • 1
  • Hello welcome! can you please share subset of the data which read in your `data` variable? It would help SO members reproduce your example. – CaseebRamos May 14 '20 at 01:05

1 Answers1

2

The problem might be specifying the ax in a list.. not very sure how that is going to work. You can always flatten out the axis and iterate through your labels and y-axis values to plot, for example:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

x = "Subregion"
hue = "Mutation"
kind = "violin"
title_name = "M1"

M1 = pd.DataFrame(np.random.normal(0,1,(100,6)),
                  columns=["Area_mm","DAPI_count","SST_count","DAPI_per_area","SST_per_area","SST_per_DAPI"])
M1['x'] = np.random.choice(['p','q','r'],100)
M1["Mutation"] = np.random.choice(['A','B'],100)

VAR = M1.columns[:6]
YL = ["Area (mm^2)","DAPI Cell Count","SST Cell Count","DAPI Cell Density (DAPI/mm^2)","SST Cell Density (SST/mm^2)","SST Cell Density (% SST/DAPI cells)"]

fig, axs = plt.subplots(3, 2,figsize = (8,8))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
axs = axs.reshape(-1)
for k in range(len(VAR)):
    sns.violinplot(x = "x", y = VAR[k], hue = hue, col = None, 
                kind = kind, data = M1,ax=axs[k])
    axs[k].set_ylabel(YL[k],fontsize=8)
    axs[k].legend_.remove()
axs[-1].legend(loc='upper right', ncol=1,bbox_to_anchor=(1.5,1.5))
plt.show()

enter image description here

StupidWolf
  • 45,075
  • 17
  • 40
  • 72
  • Since I am pulling from my own data and I do not need to create random numbers, should I disregard any of the lines of code you made that begin with "M1"? Also thank you so much for responding! – GKC2024 May 14 '20 at 00:46
  • 1
    yes.. I don't have your dataset, hence I need to make one to show you the code is reproducible. As good practice, it's also recommended when you ask questions, to provide a small dataset so others can reproduce your problem :) – StupidWolf May 14 '20 at 07:13