I have a matplotlib plot on which I found the coordinates of given points like this:
I am trying to find a way to add different axes on the same plot, and get the coordinates of the same points but according to the new axis system, like this:
I am very much a python beginner and I have been struggling with this. Is there a way to do that ?
I have come across a number of plots (end of page) that are very similar to scatter / swarm plots which jitter the y-axis in order avoid overlapping dots / bubbles.
How can I get the y values (ideally in an array) based on a given set of x and z values (dot sizes)?
I found the python circlify library but it's not quite what I am looking for.
Example of what I am trying to create
EDIT: For this project I need to be able to output the x, y and z values so that they can be plotted in the user's tool of choice. Therefore I am more interested in solutions that generate the y-coords rather than the actual plot.
Answer:
What you describe in your text is known as a swarm plot (or beeswarm plot) and there are python implementations of these (esp see seaborn), but also, eg, in R. That is, these plots allow adjustment of the y-position of each data point so they don't overlap, but otherwise are closely packed.
Seaborn swarm plot:
Discussion:
But the plots that you show aren't standard swarm plots (which almost always have the weird looking "arms"), but instead seem to be driven by some type of physics engine which allows for motion along x as well as y, which produces the well packed structures you see in the plots (eg, like a water drop on a spiders web).
That is, in the plot above, by imagining moving points only along the vertical axis so that it packs better, you can see that, for the most part, you can't really do it. (Honestly, maybe the data shown could be packed a bit better, but not dramatically so -- eg, the first arm from the left couldn't be improved, and if any of them could, it's only by moving one or two points inward). Instead, to get the plot like you show, you'll need some motion in x, like would be given by some type of physics engine, which hopefully is holding x close to its original value, but also allows for some variation. But that's a trade-off that needs to be decided on a data level, not a programming level.
For example, here's a plotting library, RAWGraphs, which produces a compact beeswarm plot like the Politico graphs in the question:
But critically, they give the warning:
"It’s important to keep in mind that a Beeswarm plot uses forces to avoid collision between the single elements of the visual model. While this helps to see all the circles in the visualization, it also creates some cases where circles are not placed in the exact position they should be on the linear scale of the X Axis."
Or, similarly, in notes from this this D3 package: "Other implementations use force layout, but the force layout simulation naturally tries to reach its equilibrium by pushing data points along both axes, which can be disruptive to the ordering of the data." And here's a nice demo based on D3 force layout where sliders adjust the relative forces pulling the points to their correct values.
Therefore, this plot is a compromise between a swarm plot and a violin plot (which shows a smoothed average for the distribution envelope), but both of those plots give an honest representation of the data, and in these plots, these closely packed plots representation comes at a cost of a misrepresentation of the x-position of the individual data points. Their advantage seems to be that you can color and click on the individual points (where, if you wanted you could give the actual x-data, although that's not done in the linked plots).
Seaborn violin plot:
Personally, I'm really hesitant to misrepresent the data in some unknown way (that's the outcome of a physics engine calculation but not obvious to the reader). Maybe a better compromise would be a violin filled with non-circular patches, or something like a Raincloud plot.
I created an Observable notebook to calculate the y values of a beeswarm plot with variable-sized circles. The image below gives an example of the results.
If you need to use the JavaScript code in a script, it should be straightforward to copy and paste the code for the AccurateBeeswarm class.
The algorithm simply places the points one by one, as close as possible to the x=0 line while avoiding overlaps. There are also options to add a little randomness to improve the appearance. x values are never altered; this is the one big advantage of this approach over force-directed algorithms such as the one used by RAWGraphs.
I produced a histogram which looks something like this:
Code that I used to produce this plot:
sns.countplot(table.column_name)
As you can notice, the entire histogram gets clustered at the left end due to uneven distribution of data.
How do I zoom in at the left end?
One way that I tried and it gave me a marginally better result was :
plt.xlim(0,25)
Is there a better way to do this?
Looks like the data would be better viewed on a logarithmic scale. On your matplotlib plot axis, ax, use:
ax.set_yscale('log')
The program pastebinned below generates a plot that looks like:
Pastebin: http://pastebin.com/wNgAG6K9
Basically, the program solves an equation for AA, and plots the values provided AA>0 and AA=/=0. The data is plotted using pcolormesh from 3 arrays called x, y and z (lines 57 - 59).
What I want to do:
I would like to plot a line around the boundary where the solutions go from zero (black) to non-zero (yellow/green), see plot below. What is the most sensible way to go about this?
I.e. lines in red (done crudely in MS paint)
Further info: I need to be able to store the red dashed boundary values so that I can plot the red dashed boundary condition to another 2d plot made from real/measured/non-theoretical data.
Feel free to ask for further information.
Without seeing your data, I would suggest first trying to work with matplotlib's internal algorithm to plot the contour line corresponding to the zero level. This is simple, but it might happen that the interpolation that is used for this doesn't look good enough (I don't know if it can find that sharp peak in the contour line). The proof of the pudding is in the eating:
plt.contour(x,y,z,[0],colors='r',linewidths=2,linestyles='dashed')
If that doesn't suffice, you might have to resort to image processing methods to find the boundaries of your data (after turning it into binary).
My question is:
I have x and y coordinates, both in degrees. They describe the position of the objects in a region. Now I want to plot something like a histogram, in python, like shown in the figure (done in MATLAB) below
using color codes. It tells how many objects are present over the area. The bin size is 0.5 * 0.5 deg^2. So how can I ?
Secondly, how shall I proceed if I have to plot a third axis instead of just the histogram that describes a different parameter altogether, like some number. I mean just three axes : x, y, z , z being shown in color-code.
Thirdly,
(other questions may be solved after browsing examples shown in comments, but) how to get the data of the color-histogram? To be clear enough, every bin has a particular value, so that it has been shown in the color-bar. But, how can I get the value of each bin and the corresponding points in the form of array I guess, or whatever suitable form may be available?