Seaborn Stripplot Axis Values with Correct Scaling - seaborn

I'm trying to plot some data in seaborn where the x values are percentages*100 as floating point numbers (ie 90.909). When I make the plot:
fig, ax = plt.subplots(figsize=(10,10))
ax = sns.stripplot(df_12['% ident'], df_12['length'], jitter=True)
The decimals in the floating points make the X axis unreadable:
Initial Plot
I would like to set the x axis to show only whole number multiples of 5 (ie 80, 85, 90, 95, 100).
One method I have tried is the following:
fmt = '{:0.0f}'
xticklabels = []
count = 0
for item in ax.get_xticklabels():
count+= 1
item.set_text(fmt.format(float(item.get_text())));
xticklabels += [item];
ax.set_xticklabels(xticklabels);
This succeeds in changing the axis values to integers, but the axis looks busy. The numbers shown are also inconsistent between similar datasets.
Second Plot
I would like to reduce the total number of values shown on the axis. I have tried to use
ax.xaxis.set_major_locator(plt.MaxNLocator(5))
Or similarly
ax.xaxis.set_major_locator(plt.MaxNLocator(5))
ax.set_xticklabels([80, 85, 90, 95, 100])
Which give outputs similar to this:
Third Plot
If you compare this to the previous plot, you'll notice the x axis labels no longer relate to the points plotted. How do I set the values of the x axis while still keeping them related to the points plotted?
Other things I have tried:
ax.set_xlim(75, 100)
This and any variants result in a blank plot.
ax.set(xticklabels=[75,80,85,90,95,100])
Does the same thing where the axis labels don't match the data.
ax.set(xticks=range(75,101), xticklabels=[75,80,85,90,95,100])
Results in all the data points stuck on the left side of the plot with all the axis labels overlapping on a single tick on the right.
ax.xaxis.set_major_locator(ticker.MaxNLocator(integer=True))
This doesn't change the axis values to integers, and also appears to cause the axis to no longer correlate with the data.

Related

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.

d3 floating grouped bar with ranged values in a timeline

im trying to understand what tools i need to use as im new to d3 and didnt find any thing related...
i need a area chart that is like bars but can float and be on multiple values both on the x and y axis.
in this example the values are days but it might be hours/months etc...
need to know the direction i need to go.. / the right term to search...
There's no significant difference between drawing this chart and a normal bar chart.
And you need to define some scales that will map the values in your data to co-ordinates on your chart.
You need to draw some rect shapes.
So, in the above example you would define a time scale that, given an input date, will map that to a certain x co-ordinate on your chart. You can then use that to determine both the x co-ordinate for where the left-hand-side of a rectangle will be, and to work out how wide the rectangle needs to be.
const xScale = d3.scaleTime()
.domain([d3.min(dateValuesInMyDataset, d => d.date), d3.max(dateValuesInMyDataset, d => d.date)])
.range([0, widthOfMyChart]);
The above xScale if given the earliest date in your dataset would return the value 0, because this is the x co-ordinate representing that date.
Similarly, you would want to construct a linear scale which defines how to map the numerical range of values in your dataset, to the y co-ordinates in your chart. Then you can use the scale to determine the y value and height of all of the rectangles in your chart.
There are lots of good examples of this on ObservableHQ.com that you can browse and see the code for.

Change pixel values on a line in MATLAB

I wish to set values on a line whose endpoints are returned by the hough transforms to zero. I have written the following code snippet
imshow(img);
hold on
img_black = img;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2]; %line end points
[x, y] = bresenham(xy(1,1),xy(1,2),xy(2,1),xy(2,2)); %returns all points on the line
for i = 1:length(x)
plot(x(i),y(i),'*'); %to plot individual pixels on line itself
img_black(x(i),y(i),:) = [0,0,0]; %set rgb values to zero
end
end
Although the points plotted on the image below are as expected
The image where the corresponding pixel values are being set to zero is not as expected.
What is happening here?
It looks like you have mixed up x and y with rows and columns.
img_black(x(i), y(i),:)
Should be
img_black(y(i), x(i),:);
This is because the first dimension of img_black is rows (y) and the second dimension is columns (x).
The resulting image looks like it does because your lines go the wrong way and (sometimes) go outside the bounds of the original image, but MATLAB gladly expands your image (with zeros) and sets the values that you request, hence all the black pixels on the right.
NOTE: This switching back and forth between row, column and x,y is common throughout MATLAB's built-in functions and you should always be careful to note what the output is. A class example is meshgrid vs ndgrid outputs.

seaborn kdeplot x axis scaling?

I have a histogram of my data:
h is a 1-d array of counts
x is a 1-d array of bin values
Now if I do:
sns.kdeplot(h, shade=True);
I get a plot where x-axis goes from -20 to 100, which has nothing to do with
my original x data. How do I get the x-axis scaled to match my data?
I see I misunderstood the input to kde. It wants the original values. I had already created a histogram and wanted to feed that to kde.
In my histogram I have h.buckets, and h.results. I did
def hist_to_values (hist):
ret = []
for x,y in zip (hist.buckets, h.results):
ret.extend ([x] * y)
return np.array (ret)
Then feed this to kde, and I got the results I expect.

Display different values on axis than those found by the scale function in D3

I have a d3 graph that uses a linear scale for its x axis. It looks something like this:
...
y |
|
+-------------------------------------------
0.0 0.5 1.0 1.5 2.0 2.5 3.0
Time in weeks
Beneath this axis I want to display rows of data aligned to the x axis. Like this:
23 23 22 19
Using this data:
var nums = [23, 23, 22, 19];
var times = [0, 0.5, 1.5, 3];
times are where the nums should fall on the Time in weeks x axis. So the first index of nums falls under 0.0, the second under 0.5, and so on.
The scale function looks something like this:
var x = d3.scale.linear().domain([0,3]).range([0, 600]);
So x(0.5) returns the correct range value for displaying a tick on the new axis. But what I want to display is the corresponding value from the nums array. That is, display the value of nums[times.indexOf(0.5)].
Is there a way to override scale() as used by d3.svg.axis() so that it displays nums values instead of times values while still using times as the input domain?
Edit
Here is a demo
Edit 2
I figured it out thanks to ne8il's answer. The answer was not complete, but it formed the basis for this code:
var x1Axis = d3.svg.axis()
.scale(x1)
.ticks(nums)
.tickValues(times)
.tickFormat(function(x){return nums[times.indexOf(x)];})
Working example
I believe in this case you can do
d3.svg.axis().ticks(times).tickValues(nums);
It will pass each 'time' into your scale function to map it to an x coordinate, and use the corresponding indexed value in 'nums' to output text.
Source is here

Resources