Plot 2D graph using Bokeh - python

I'm trying to plot a graph using Bokeh.
I did it using matplotlib but I can't figure out how I can plot 2D array using Bokeh.
This is my code for plotting with matplotlib:
[row, col] = point_data.shape
# select columns names
text = point_data.columns
# find string index:
range_ind = np.array(text.str.find('Range_cm')) > -1
range_cm_mat = point_data.iloc[0:row, range_ind].values
plt.figure(figsize=(19, 10))
plt.plot(range_cm_mat, '.', markersize=0.5, color='#1f77b4')
plt.show()
My data I'm plotting is from a CSV file and it is filtered by the string above.
Please help me figure out how I can show this plot with Bokeh library
This is what I tried and it isn't the way...
def make_scatter(title, x_title, y_title, x, y):
p = figure(title=title, toolbar_location="below", background_fill_color="#fafafa")
p.circle(x, y) # , alpha=0.5)
p.y_range.start = 0
p.legend.location = "center_right"
p.legend.background_fill_color = "#fefefe"
p.xaxis.axis_label = x_title
p.yaxis.axis_label = y_title
p.grid.grid_line_color = "white"
return p
x = np.arange(1, np.size(plot[0]), 1)
for i in range (np.size(plot[0])):
p1 = make_scatter("Range/Frames", 'Range [m]', 'Frames', [pt[i] for pt in plot], x)
show(p1)
This is how the data looks like:
2D array:

Related

Matplotlib Draw a Constant y Axis

I want to use matpoltlib to make a plot that with a constant y axis(always from 0 to 14 and the gap is 1), since I want to make labels for them and my dot values will be(x, y) where y is from 0 to 14 gap 1, and a changing x axis. I already tried to play with y ticks. And here is my code for that:
fig, ax = plt.subplots()
fig.canvas.draw()
plt.yticks(np.arange(0, 14, 1))
labels = [item.get_text() for item in ax.get_yticklabels()]
labels[1] = 'Not Detected'
labels[2] = 'A/G'
labels[3] = 'G/G'
labels[4] = 'C/T'
labels[5] = 'C/C'
labels[6] = 'A/A'
labels[7] = '-1'
labels[8] = 'ε3/ε3'
labels[9] = 'A/C'
labels[10] = 'T/T'
labels[11] = 'C/G'
labels[12] = 'ε2/ε3'
labels[13] = 'G/T'
ax.set_yticklabels(labels)
what I'm thinking about is to use some values or lines with white color so those y axis will appear. But I'm looking for a more efficient way of doing it. And here is the diagram I generated with the current code. It only shows C/C right now and I want all labels to appear in the diagram.
I tried draw white points with:
x1 = np.arange(n)
y1 = np.arange(1,15,1)
plt.scatter(x1,y1,color = 'white')
Which did give me what I want: But I was wondering whether there is a lib setting that can do this.
I would recommend just using a fixed locator and fixed formatter for your y axis. The function, ax.set_yticklabels() is simply a convenience wrapper for these tick methods.
I would also recommend having your y_labels in a list or using a loop structure as this is a more generalizable and modifiable implementation.
If I'm understanding the goals of your plot correctly, something like this may work well for you.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
#make some data
x = np.arange(25)
y = np.random.randint(1, 14, size=25)
#convert y labels to a list
y_labels = [
'Not Detected','A/G','G/G','C/T','C/C','A/A',
'-1','ε3/ε3', 'A/C','T/T','C/G','ε2/ε3','G/T'
]
#define figure/ax and set figsize
fig, ax = plt.subplots(figsize=(12,8))
#plot data, s is marker size, it's points squared
ax.scatter(x, y, marker='x', s=10**2, color='#5d2287', linewidth=2)
#set major locator and formatter to fixed, add grid, hide top/right spines
locator = ax.yaxis.set_major_locator(mpl.ticker.FixedLocator(np.arange(1, 14)))
formatter = ax.yaxis.set_major_formatter(mpl.ticker.FixedFormatter(y_labels))
grid = ax.grid(axis='y', dashes=(8,3), alpha=0.3, color='gray')
spines = [ax.spines[x].set_visible(False) for x in ['top','right']]
params = ax.tick_params(labelsize=12) #increase label font size

Python matplotlib polar coordinate is not plotting as it is supposed to be

I am plotting from a CSV file that contains Cartesian coordinates and I want to change it to Polar coordinates, then plot using the Polar coordinates.
Here is the code
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
df = pd.read_csv('test_for_plotting.csv',index_col = 0)
x_temp = df['x'].values
y_temp = df['y'].values
df['radius'] = np.sqrt( np.power(x_temp,2) + np.power(y_temp,2) )
df['theta'] = np.arctan2(y_temp,x_temp)
df['degrees'] = np.degrees(df['theta'].values)
df['radians'] = np.radians(df['degrees'].values)
ax = plt.axes(polar = True)
ax.set_aspect('equal')
ax.axis("off")
sns.set(rc={'axes.facecolor':'white', 'figure.facecolor':'white','figure.figsize':(10,10)})
# sns.scatterplot(data = df, x = 'x',y = 'y', s= 1,alpha = 0.1, color = 'black',ax = ax)
sns.scatterplot(data = df, x = 'radians',y = 'radius', s= 1,alpha = 0.1, color = 'black',ax = ax)
plt.tight_layout()
plt.show()
Here is the dataset
If you run this command using polar = False and use this line to plot sns.scatterplot(data = df, x = 'x',y = 'y', s= 1,alpha = 0.1, color = 'black',ax = ax) it will result in this picture
now after setting polar = True and run this line to plot sns.scatterplot(data = df, x = 'radians',y = 'radius', s= 1,alpha = 0.1, color = 'black',ax = ax) It is supposed to give you this
But it is not working as if you run the actual code the shape in the Polar format is the same as Cartesian which does not make sense and it does not match the picture I showed you for polar (If you are wondering where did I get the second picture from, I plotted it using R)
I would appreciate your help and insights and thanks in advance!
For a polar plot, the "x-axis" represents the angle in radians. So, you need to switch x and y, and convert the angles to radians (I also added ax=ax, as the axes was created explicitly):
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
data = {'radius': [0, 0.5, 1, 1.5, 2, 2.5], 'degrees': [0, 25, 75, 155, 245, 335]}
df_temp = pd.DataFrame(data)
ax = plt.axes(polar=True)
sns.scatterplot(x=np.radians(df_temp['degrees']), y=df_temp['radius'].to_numpy(),
s=100, alpha=1, color='black', ax=ax)
for deg, y in zip(df_temp['degrees'], df_temp['radius']):
x = np.radians(deg)
ax.axvline(x, color='skyblue', ls=':')
ax.text(x, y, f' {deg}', color='crimson')
ax.set_rlabel_position(-15) # Move radial labels away from plotted dots
plt.tight_layout()
plt.show()
About your new question: if you have an xy plot, and you convert these xy values to polar coordinates, and then plot these on a polar plot, you'll get again the same plot.
After some more testing with the data, I decided to create the plot directly with matplotlib, as seaborn makes some changes that don't have exactly equal effects across seaborn and matplotlib versions.
What seems to be happening in R:
The angles (given by "x") are spread out to fill the range (0,2 pi). This either requires a rescaling of x, or change how the x-values are mapped to angles. One way to get this, is subtracting the minimum. And with that result divide by the new maximum and multiply by 2 pi.
The 0 of the angles it at the top, and the angles go clockwise.
The following code should create the plot with Python. You might want to experiment with alpha and with s in the scatter plot options. (Default the scatter dots get an outline, which often isn't desired when working with very small dots, and can be removed by lw=0.)
ax = plt.axes(polar=True)
ax.set_aspect('equal')
ax.axis('off')
x_temp = df['x'].to_numpy()
y_temp = df['y'].to_numpy()
x_temp -= x_temp.min()
x_temp = x_temp / x_temp.max() * 2 * np.pi
ax.scatter(x=x_temp, y=y_temp, s=0.05, alpha=1, color='black', lw=0)
ax.set_rlim(y_temp.min(), y_temp.max())
ax.set_theta_zero_location("N") # set zero at the north (top)
ax.set_theta_direction(-1) # go clockwise
plt.show()
At the left the resulting image, at the right using the y-values for coloring (ax.scatter(..., c=y_temp, s=0.05, alpha=1, cmap='plasma_r', lw=0)):

Trying to export 6 violin subplots (made using seaborn) (formatted into 3 rows and 2 columns) to a single page PDF

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

How to rotate matplotlib bar-chart?

The following code is used to produce a barchart. I would like to rotate it so that it becomes vertical e.g. the current labels at the x axis go to the y axis ,the current y axis labels to the x axis and the bars rotate accordingly.
I am new to matplotlib and python so any help would be welcomed.
def plot_coefficients(classifier, feature_names, top_features=40):
if classifier.__class__.__name__ == 'SVC':
coef = classifier.coef_
coef2 = coef.toarray().ravel()
coef1 = coef2[:len(feature_names)]
else:
coef2 = classifier.coef_.ravel()
coef1 = coef2[:len(feature_names)]
top_positive_coefficients = np.argsort(coef1)[-top_features:]
top_negative_coefficients = np.argsort(coef1)[:top_features]
top_coefficients = np.hstack([top_negative_coefficients, top_positive_coefficients])
# create plot
plt.figure(figsize=(15, 5))
colors = ['red' if c < 0 else 'blue' for c in coef1[top_coefficients]]
plt.bar(np.arange(2 * top_features), coef1[top_coefficients], color=colors)
feature_names = np.array(feature_names)
plt.xticks(np.arange(1, 1 + 2 * top_features), feature_names[top_coefficients], rotation=90, ha='right')
plt.show()
Update
Expected output:
Look at the matplotlib method barh. You can find example from: https://matplotlib.org/gallery/lines_bars_and_markers/barh.html

Combining an imshow colormap with Python Pandas subplot line charts

I have a Pandas DataFrame that has pairs of columns -- each pair has a measurement column that I want to plot as a line chart and another column that I want to plot as an imshow colormap to illustrate a severity metric.
A simple example:
from random import *
import pandas as pd
randBinList = lambda n: [randint(0,1) for b in range(1,n+1)]
rng = pd.date_range('1/1/2011', periods=72, freq='H')
tslist = {}
for measurement_num in range(3):
measurement_name = 'Measurement'+str(measurement_num)
tslist[measurement_name] = pd.DataFrame({'Value': randn(len(rng)),'Severity': randn(len(rng))})
ts = pd.concat(tslist, axis=1)
ts.head()
Results in a simple DataFrame:
My attempt to create my intended plot is based on: Shade the background of matplotlib based on array and colormap and Colormap entire subplot
PointList = ts.columns.levels[0].tolist()
y = ts[PointList[0]]['Value'].values
x = np.arange(len(y))
t = ts[PointList[0]]['Severity'].values
fig, ax = plt.subplots(len(PointList), 1, figsize=(18,10))
ax[0].plot(x, y, c='black')
ymin, ymax = ax[0].get_ybound()
xmin, xmax = ax[0].get_xbound()
im = ax[1].imshow(t.reshape(1, t.size), extent=[xmin,x.max(),ymin,ymax], alpha=.5, cmap=plt.cm.RdYlGn)
ax[0].set_title(PointList[0])
plotcounter = 1
for point in PointList[1:]:
y = ts[point]['Value'].truncate(before=cutoffdate).values
x = np.arange(len(y))
t = ts[point]['Severity'].truncate(before=cutoffdate).values
ax[plotcounter].plot(x, y, c='black', )
ymin, ymax = ax[plotcounter].get_ybound()
xmin, xmax = ax[plotcounter].get_xbound()
im = ax[plotcounter].imshow(t.reshape(1, t.size), extent=[xmin,x.max(),ymin,ymax], alpha=.5, cmap=plt.cm.RdYlGn)
ax[plotcounter].set_aspect(ax[0].get_aspect())
ax[plotcounter].set_title(point)
plotcounter += 1
plt.tight_layout()
plt.show()
which results in:
I'm having trouble with imshow for the first subplot. I'm looking for a much more elegant solution that integrates better with Pandas and results in subplots. Also I'd like to use the pandas.tseries.index.DatetimeIndex as the x-axis instead of having only numbers.

Categories

Resources