How can I decrease the width of a boxplot rectangle? - seaborn

I've made a boxplot:
I would like to decrease the width of the blue/orange rectangle to get a width like the blue/orange rectangles in this boxplot:
My goal is it to decrease the total width of the boxplot so that it takes less space in a document / I can have text flow beside the plot picture.
Code so far:
ax_v = sns.boxplot(x="hasTopic", y="sentiment_sum", data=videos, orient="v")
ax_v.set(xticklabels=["ohne", "mit"])
ax_v.set(ylim=(-4, 4))
plt.xlabel('Themenbezug Videos', fontsize=14)
plt.ylabel('Sentiment', fontsize=14)
plt.show()
How can I do that in Seaborn?

plt.figure(figsize=(3.4, 4)) # <- this line
ax_v = sns.boxplot(x="hasTopic", y="sentiment_sum", data=videos, width=0.5, orient="v")
ax_v.set(xticklabels=["ohne", "mit"])
ax_v.set(ylim=(-4, 4))
plt.xlabel('Themenbezug Videos', fontsize=14)
plt.ylabel('Sentiment', fontsize=14)
plt.show()
solved it.
To color each rectangle with custom colors use:
my_pal = {0: "#3399ff", 1: "#f1c40f"} # x="hasTopic" has value 0 or 1
plt.figure(figsize=(3.4, 4), dpi=800)
ax_c = sns.violinplot(x="hasTopic", y="sentiment_sum", palette=my_pal, width=0.7, orient="v", data=channels)
ax_c.yaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
#ax_v = sns.swarmplot(x="hasTopic", y="sentiment_sum", data=comments, color=".25")
ax_c.set(xticklabels=["ohne", "mit"])
ax_c.set(ylim=(-4, 4))
plt.xlabel('Themenbezug Channels', fontsize=14)
plt.ylabel('Sentiment', fontsize=14)
plt.tight_layout()
plt.show()

Related

How do you rotate axis text on Seaborn JointGrid?

How do you rotate the text along the x-axis to avoid unreadable text like the one above?
plt.figure(figsize = (10,8))
g = sns.JointGrid(x='u',y='t',data = tdata)
g.plot(sns.scatterplot, sns.histplot)
plt.show()
And plt.figure also can't work on JoinGrid,
You can get axes with g.ax_joint and from here your can set you axis attributes.
Solution 1: tick_params()
plt.figure(figsize=(10, 8))
g = sns.JointGrid(x="u", y="t", data=tdata)
g.plot(sns.scatterplot, sns.histplot)
g.ax_joint.tick_params(axis="x", rotation=90)
plt.show()
Solution 2: set_xticklabels()
plt.figure(figsize=(10, 8))
g = sns.JointGrid(x="u", y="t", data=tdata)
g.plot(sns.scatterplot, sns.histplot)
g.ax_joint.set_xticklabels(g.ax_joint.get_xticks(), rotation=45)
plt.show()
Solution 3: get_xticklabels()
With this you can iterate over all the ticks and change their rotation individually.
plt.figure(figsize=(10, 8))
g = sns.JointGrid(x="u", y="t", data=tdata)
g.plot(sns.scatterplot, sns.histplot)
for tick in g.ax_joint.get_xticklabels():
tick.set_rotation(30)
plt.show()
PS:
xticklabels can be different for precision based on the precision value return by each function.

Python Plotly - How to overlay grid lines on a contour plot?

I am using python plotly and am trying to overlay grid lines on a contour plot. The following code does not generate an error but it also does not show grid lines. How can I make the grid lines show?
I didn't find a good way. The grid layer is there (you can see it if you add opacity<1 in your contour) but you cannot put the grid layer above the traces (or at least I didn't find a way reading the doc and the code).
I ended up rebuilding the grid on top:
def add_box(lfig, x, y):
lfig.add_trace(go.Scatter(
x=x,
y=y,
opacity=0.5,
marker_color='white',
line_width=1,
))
def compute_horizontal_lines(x_min, x_max, y_data):
x = np.tile([x_min, x_max, None], len(y_data))
y = np.ndarray.flatten(np.array([[a, a, None] for a in y_data]))
return x, y
def compute_vertical_lines(y_min, y_max, x_data):
y = np.tile([y_min, y_max, None], len(x_data))
x = np.ndarray.flatten(np.array([[a, a, None] for a in x_data]))
return x, y
hx, hy = compute_horizontal_lines(200, 20000, range(-150, 180, 30))
vrange = [100*i for i in range(3, 9)] + [1000*i for i in range(1, 10)] + [10000+1000*i for i in range(1, 5)]
vx, vy = compute_vertical_lines(-180, 180, vrange)
add_box(fig, hx, hy)
add_box(fig, vx, vy)
fig.show()
which give me something like:
contour plot with a grid on top

Flip over colorbar of Seaborn heatmap

I am trying to flip over the colorbar of my Heatmap in Seaborn.
Here is how it looks at the moment.
What I would like to have is the colorbar starting from the top
with the value 0 (Green) and going to the bottom with the value 8 (red).
Please note that the Y-axis points are sorted based on the average values
from min (top) to max (bottom) and I would like to keep them this way.
Any idea if it is possible to do that?
Here is an example of the current code:
cmap1 = mcolors.LinearSegmentedColormap.from_list("n",['#00FF00','#12FF00','#24FF00','#35FF00','#47FF00','#58FF00','#6AFF00','#7CFF00','#8DFF00','#9FFF00','#B0FF00','#C2FF00','#D4FF00','#E5FF00','#F7FF00','#FFF600','#FFE400','#FFD300','#FFC100','#FFAF00','#FF9E00','#FF8C00','#FF7B00','#FF6900','#FF5700','#FF4600','#FF3400','#FF2300','#FF1100','#FF0000',])
plt.figure(figsize=(22, 12))
df = pd.DataFrame( AgainReorderindSortedEDPList, index=sortedProgrammingLanguagesBasedOnAverage, columns=sortedTasksBasedOnAverage)
mask = df.isnull()
sns.heatmap(df, annot=True, fmt="g", cmap=cmap1, mask=mask)
plt.yticks(fontsize = 12)
plt.yticks(rotation=0)
plt.xticks(fontsize = 11)
plt.ylabel('Programming Languages', size = 15)
plt.xlabel('Programming Tasks', size = 15)
plt.xticks(rotation=-45)
plt.show()
The AgainReorderindSortedEDPList, sortedProgrammingLanguagesBasedOnAverage, and sortedTasksBasedOnAverage
are the data I am using to plot this heatmap.
You simply need to call invert_yaxis() on the axes that contain the colorbar. How to do that depends a bit on how you are creating your heatmap, but unfortunately you have not provided your code.
Here is the most simple example:
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data)
plt.gcf().axes[1].invert_yaxis()
plt.gcf() gets a reference to the current figure. Figure.axes is a list of axes in the figure. axes[1] is the second axes, which should correspond to the axes created by heatmap to plot the colorbar.

Comparing Histograms of RGB values from image in Matlab

So I want the RGB values of an image placed into an histogram and then that histogram will be compared to other image's histogram.
Currently this is the code:
if (size(cimg, 3) ~= 3)
error('rgbhist:numberOfSamples', 'Input image must be RGB.')
end
nBins = 256;
rHist = imhist(cimg(:,:,1), nBins);
gHist = imhist(cimg(:,:,2), nBins);
bHist = imhist(cimg(:,:,3), nBins);
hFig = figure;
%figure
subplot(1,2,1);imshow(cimg)
subplot(1,2,2);
hold on
h(1) = stem(1:256, rHist); %hold on
h(2) = stem(1:256 + 1/3, gHist, 'g');
h(3) = stem(1:256 + 2/3, bHist, 'b');
hold off
set(h, 'marker', 'none')
set(h(1), 'color', [1 0 0])
set(h(2), 'color', [0 1 0])
set(h(3), 'color', [0 0 1])
axis square
The code outputs the image along with its RGB histogram value, how can I use that histogram to compare it with other histograms so that I could potentially classify the image as having nearly the same colors as that of another image?
You could use Kullback Leibler Divergence to calculate the distance between 2 histograms.
This is easy as you can treat the Histogram as a distribution.
Since the KL Divergence isn't symmetric one could compute it twice (Namely [X, Y] and [Y, X]) and take the average.

Pixels from plot: getframe is too slow

I need to do the following:
I have a fixed environment with a point in it
At each time step the point moves and I need to take a screenshot of the current status (environment + point)
What I do is
function getPixels(state)
fig = figure('visible','off')
hold all
plot_environment() % calls patch and other stuff
plot(state(1),state(2),'r+')
f = getframe();
data = f.cdata;
close(fig)
The problem is that it is very slow (0.6s which for me is really too much).
I tried using persistent fig and I can go down to 0.4s, still too much.
I read about using print or hardcopy, but it did not help. Even reducing the number of pixels by -r20 (1/5 of my default size) did not speed it up.
Any suggestion? Is there a faster way to get the pixels?
EDIT: ADDITIONAL DETAILS
The state is just a 2d point.
The environment is defined by some fixed known variables used to draw shapes. More specifically I have some points
points = [c11 c12
c21 c22
.....]
used to patch rectangles, circles and triangles. For this I use patch and circles.
So in the end I want to plot everything together and get the resulting pixels. Is there a way to do it without getframe or a way to speed it up?
COMPLETE EXAMPLE
It requires circles.
Launch tic, getPixels([0.1, 0.2]'); toc
It takes 0.43s on average. The getframe command alone takes 0.29s.
function data = getPixels(state)
fig = figure('visible','off');
hold all
c1 = [0.1 0.75;
0.45 0.75];
c2 = [0.45 0.4;
0.45 0.8];
radius = 0.1;
grey = [0.4,0.4,0.4];
% Circles
p = [c1; c2];
circles(p(:,1), p(:,2), radius, 'color', grey, 'edgecolor', grey)
% Rectangles
patch([0.1 0.45 0.45 0.1], [0.65 0.65 0.85 0.85], grey, 'EdgeAlpha', 0)
patch([0.35 0.55 0.55 0.35], [0.4 0.4 0.8 0.8], grey, 'EdgeAlpha', 0)
% Triangle
x = [0.95, 1.0, 1.0];
y = [1.0, 0.95, 1.0];
fill(x, y, 'r')
axis([0 1 0 1])
box on
axis square
% Point
plot(state(1),state(2),'ro','MarkerSize',8,'MarkerFaceColor','r');
f = getframe();
data = f.cdata;
close(fig)
You can reduce the execution time of Matlab's getframe() function by a factor of ten. The trick consists of not creating a figure each time you call the getPixels() function but using an existing one. You may pass the figure handle via the function parameters. And use the Matlab's function clf that clears the current figure window between two calls.
EDIT
Here is an example of the way I play with figure et getframe.
The following performance chart
is given by
%%
clear al
close all
clc
nbSim = 10 %number of getframe calls
tElapsed = zeros(nbSim, 2); %two types of getting frames
%% METHOD 1: figure within loop
for ind_sim = 1:nbSim
fig = figure;
%some graphical elements
hold all
patch(rand(1,4), rand(1,4), rand(1,3), 'EdgeAlpha', 0)
patch(rand(1,4), rand(1,4), rand(1,3), 'EdgeAlpha', 0)
fill(rand(1,3), rand(1,3), 'r')
plot(rand,rand,'ro','MarkerSize',8,'MarkerFaceColor','k');
%some axes properties
axis([0 1 0 1])
box on
axis square
tStart = tic;
f = getframe();
tElapsed(ind_sim,1) = toc(tStart);
data = f.cdata;
close(fig)
end
%% METHOD 2: figure outside loop
fig = figure;
for ind_sim = 1:nbSim
%some graphical elements
hold all
patch(rand(1,4), rand(1,4), rand(1,3), 'EdgeAlpha', 0)
patch(rand(1,4), rand(1,4), rand(1,3), 'EdgeAlpha', 0)
fill(rand(1,3), rand(1,3), 'r')
plot(rand,rand,'ro','MarkerSize',8,'MarkerFaceColor','k');
%some axes properties
axis([0 1 0 1])
box on
axis square
tStart = tic;
f = getframe();
tElapsed(ind_sim,2) = toc(tStart);
data = f.cdata;
clf
end
close(fig)
%% plot results
plot(tElapsed);
set(gca, 'YLim', [0 max(tElapsed(:))+0.1])
xlabel('Number of calls');
ylabel('Execution time');
legend({'within (method 1)';'outside (method 2)'});
title('GetFrame exectution time');
You have to drop the creation of a figure, even if it is declared not visible. This impairs the execution times.

Resources