I want to fix/set (not increase) the distance between the plotting area and the x-axis label in plotnine/ggplot.
library(ggplot2)
ggplot(diamonds)
ggplot(diamonds) + geom_point(aes(x=carat, y=price, color=cut)) + geom_smooth(aes(x=carat, y=price, color=cut))
I want to fix the distance between the two red bars on . I would like to be able to have x-ticklabels that take up more space (rotated, larger font etc.) without affecting where the x-axis label is located relative to the plot. I have found many examples to adjust the spacing - but not manually set it.
This might be an R specific solution, I don't know how plotnine works under the hood. In R, the height of the x-axis label is determined dynamically by the dimensions of the text, and there is no convenient way of setting this manually (afaik).
Instead, one can edit the height of that row in the gtable and then plot the result.
library(ggplot2)
library(grid)
p <- ggplot(diamonds) +
geom_point(aes(x=carat, y=price, color=cut)) +
geom_smooth(aes(x=carat, y=price, color=cut))
# Convert plot to gtable
gt <- ggplotGrob(p)
#> `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
# Find row in gtable where the bottom axis is located
axis_row <- with(gt$layout, t[grep("axis-b", name)])
# Manually set the height of that row
gt$heights[axis_row] <- unit(2, "cm")
# Display new plot
grid.newpage(); grid.draw(gt)
Created on 2021-08-17 by the reprex package (v1.0.0)
I'm trying to get the plot to show on a graph but it does not show anything for some reason. I have properly imported the matplotlib library, I am properly getting the values from the function and when I pass those values to the function where I want the plot to be shown it displays blank image. To show that I am getting the correct values I have used print along with plotting commands the values are getting printed but not the plot Here's the code. I was able to get the plot correct using
def GetCounts(data):
return (data['Sex'].value_counts())
def Get_Plot(Points):
_x1 = Points[0]
_x2 = Points[1]
_y = (_x1 + _x2) - 200
print('male' + ' ' + str(_x1) + '\n','female' + ' '+ str(_x2), _y)
plt.bar(height = _x1, tick_label = 'Male', left = _x1)
plt.xlabel('Counts of people according to Sex')
plt.ylabel('Number of people')
plt.show()
Counts = GetCounts(titanic)
Get_Plot(Counts)
I'm trying to get 2 bars placed in there 'Male' and 'Female' and I not sure how I will be able to. and with the code above I am only able to put only one of it.
Please help thanks in advance.
You may want to revisit the plt.bar documentation where it says
pyplot.bar(left, height, width=0.8, bottom=None, hold=None, data=None, **kwargs)
[...]
left : sequence of scalars
the x coordinates of the left sides of the bars
height : scalar or sequence of scalars
the height(s) of the bars
You may thus position the bars at the indizes 0 and 1 and their height will be given by Points
plt.bar(range(len(Points)),Points)
plt.xticks(range(len(Points)), Points.index)
I'm currently trying to create a coloured grid plot on a logarithmic scale using . As I want to include the area from 0 to 1, I'm using "symlog" as a scale instead of "log".
fig, ax = plt.subplots()
Z = np.random.random(size=(RATE_EXPONENT + 1, BLOCK_EXPONENT + 1))
x_edges = [0] + [AXIS_BASE ** i for i in range(RATE_EXPONENT + 1)]
y_edges = [0] + [AXIS_BASE ** i for i in range(BLOCK_EXPONENT + 1)]
ax.set_xbound(0.0, MAX_FEE_RATE)
ax.set_ybound(0.0, MAX_CONFIRMATION_BLOCKS)
ax.set_xlabel('Fee rate in satoshis / byte')
ax.set_ylabel('Confirmation time in blocks')
ax.set_xscale('symlog')
ax.set_yscale('symlog')
ax.set_xticks(x_edges)
ax.set_yticks(y_edges)
ax.get_xaxis().set_major_formatter(ticker.ScalarFormatter())
ax.get_yaxis().set_major_formatter(ticker.ScalarFormatter())
colour_map = colors.LinearSegmentedColormap.from_list('GreenRed', ['red', 'green'], N=256)
ax.pcolorfast(x_edges, y_edges, Z, cmap=colour_map)
plt.show()
Unfortunately, the edges aren't quite predictably spaced to the point where I'd know how to input my data and in fact, the edges are moved depending on the zoom factor.
For reference, this is what it looks like all zoomed out
and this is what it looks like when you zoom into the interval from 2 to 4
As you can see, the grid edges move as I zoom in. I'd also like for the edges to be placed at the same intervals as the axis ticks, however I've not found anything useful in the pyplot docs.
Any help would be much appreciated!
PS: Using a linear instead of a symlog scale works. Same thing when using xlim / ylim.
Use matplotlib.pyplot.pcolormesh instead of matplotlib.axes.Axes.pcolorfast. The docstring of pcolorfast says that it is experimental and
"...it lacks support for log scaling of the axes...",
as of the current version 2.0.0.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
I need to draw ternary/triangle plots representing mole fractions (x, y, z) of various substances/mixtures (x + y + z = 1). Each plot represents iso-valued substances, e.g. substances which have the same melting point. The plots need to be drawn on the same triangle with different colors/symbols and it would be nice if I could also connect the dots.
I have looked at matplotlib, R and gnuplot, but they don't seem to be able to draw this kind of plot. The 3rd party ade4 package for R seems to be able to draw it, but I'm not sure if I can draw multiple plots on the same triangle.
I need something that runs under Linux or Windows. I'm open to any suggestions, including libraries for other languages, e.g. Perl, PHP, Ruby, C# and Java.
Created a very basic script for generating ternary (or more) plots. No gridlines or ticklines, but those wouldn't be too hard to add using the vectors in the "basis" array.
from pylab import *
def ternaryPlot(
data,
# Scale data for ternary plot (i.e. a + b + c = 1)
scaling=True,
# Direction of first vertex.
start_angle=90,
# Orient labels perpendicular to vertices.
rotate_labels=True,
# Labels for vertices.
labels=('one','two','three'),
# Can accomodate more than 3 dimensions if desired.
sides=3,
# Offset for label from vertex (percent of distance from origin).
label_offset=0.10,
# Any matplotlib keyword args for plots.
edge_args={'color':'black','linewidth':2},
# Any matplotlib keyword args for figures.
fig_args = {'figsize':(8,8),'facecolor':'white','edgecolor':'white'},
):
'''
This will create a basic "ternary" plot (or quaternary, etc.)
'''
basis = array(
[
[
cos(2*_*pi/sides + start_angle*pi/180),
sin(2*_*pi/sides + start_angle*pi/180)
]
for _ in range(sides)
]
)
# If data is Nxsides, newdata is Nx2.
if scaling:
# Scales data for you.
newdata = dot((data.T / data.sum(-1)).T,basis)
else:
# Assumes data already sums to 1.
newdata = dot(data,basis)
fig = figure(**fig_args)
ax = fig.add_subplot(111)
for i,l in enumerate(labels):
if i >= sides:
break
x = basis[i,0]
y = basis[i,1]
if rotate_labels:
angle = 180*arctan(y/x)/pi + 90
if angle > 90 and angle <= 270:
angle = mod(angle + 180,360)
else:
angle = 0
ax.text(
x*(1 + label_offset),
y*(1 + label_offset),
l,
horizontalalignment='center',
verticalalignment='center',
rotation=angle
)
# Clear normal matplotlib axes graphics.
ax.set_xticks(())
ax.set_yticks(())
ax.set_frame_on(False)
# Plot border
ax.plot(
[basis[_,0] for _ in range(sides) + [0,]],
[basis[_,1] for _ in range(sides) + [0,]],
**edge_args
)
return newdata,ax
if __name__ == '__main__':
k = 0.5
s = 1000
data = vstack((
array([k,0,0]) + rand(s,3),
array([0,k,0]) + rand(s,3),
array([0,0,k]) + rand(s,3)
))
color = array([[1,0,0]]*s + [[0,1,0]]*s + [[0,0,1]]*s)
newdata,ax = ternaryPlot(data)
ax.scatter(
newdata[:,0],
newdata[:,1],
s=2,
alpha=0.5,
color=color
)
show()
R has an external package called VCD which should do what you want.
The documentation is very good (122 page manual distributed w/ the package); there's also a book by the same name, Visual Display of Quantitative Information, by the package's author (Prof. Michael Friendly).
To create ternary plots using vcd, just call ternaryplot() and pass in an m x 3 matrix, i.e., a matrix with three columns.
The method signature is very simple; only a single parameter (the m x 3 data matrix) is required; and all of the keyword parameters relate to the plot's aesthetics, except for scale, which when set to 1, normalizes the data column-wise.
To plot data points on the ternary plot, the coordinates for a given point are calculated as the gravity center of mass points in which each feature value comprising the data matrix is a separate weight, hence the coordinates of a point V(a, b, c) are
V(b, c/2, c * (3^.5)/2
To generate the diagram below, i just created some fake data to represent four different chemical mixtures, each comprised of varying fractions of three substances (x, y, z). I scaled the input (so x + y + z = 1) but the function will do it for you if you pass in a value for its 'scale' parameter (in fact, the default is 1, which i believe is what your question requires). I used different colors & symbols to represent the four data points, but you can also just use a single color/symbol and label each point (via the 'id' argument).
A package I have authored in R has just been accepted for CRAN, webpage is www.ggtern.com:
It is based off ggplot2, which I have used as a platform. The driving force for me, was a desire to have consistency in my work, and, since I use ggplot2 heavily, development of the package was a logical progression.
For those of you who use ggplot2, use of ggtern should be a breeze, and, here is a couple of demonstrations of what can be achieved.
Produced with the following code:
# Load data
data(Feldspar)
# Sort it by decreasing pressure
# (so small grobs sit on top of large grobs
Feldspar <- Feldspar[with(Feldspar, order(-P.Gpa)), ]
# Build and Render the Plot
ggtern(data = Feldspar, aes(x = An, y = Ab, z = Or)) +
#the layer
geom_point(aes(fill = T.C,
size = P.Gpa,
shape = Feldspar)) +
#scales
scale_shape_manual(values = c(21, 24)) +
scale_size_continuous(range = c(2.5, 7.5)) +
scale_fill_gradient(low = "green", high = "red") +
#theme tweaks
theme_tern_bw() +
theme(legend.position = c(0, 1),
legend.justification = c(0, 1),
legend.box.just = "left") +
#tweak guides
guides(shape= guide_legend(order =1,
override.aes=list(size=5)),
size = guide_legend(order =2),
fill = guide_colourbar(order=3)) +
#labels and title
labs(size = "Pressure/GPa",
fill = "Temperature/C") +
ggtitle("Feldspar - Elkins and Grove 1990")
Contour plots have also been patched for the ternary environment, and, an inclusion of a new geometry for representing confidence intervals via the Mahalanobis Distance.
Produced with the following code:
ggtern(data=Feldspar,aes(An,Ab,Or)) +
geom_confidence(aes(group=Feldspar,
fill=..level..,
alpha=1-..level..),
n=2000,
breaks=c(0.01,0.02,0.03,0.04,
seq(0.05,0.95,by=0.1),
0.99,0.995,0.9995),
color=NA,linetype=1) +
geom_density2d(aes(color=..level..)) +
geom_point(fill="white",aes(shape=Feldspar),size=5) +
theme_tern_bw() +
theme_tern_nogrid() +
theme(ternary.options=element_ternary(padding=0.2),
legend.position=c(0,1),
legend.justification=c(0,1),
legend.box.just="left") +
labs(color="Density",fill="Confidence",
title="Feldspar - Elkins and Grove 1990 + Confidence Levels + Density") +
scale_color_gradient(low="gray",high="magenta") +
scale_fill_gradient2(low="red",mid="orange",high="green",
midpoint=0.8) +
scale_shape_manual(values=c(21,24)) +
guides(shape= guide_legend(order =1,
override.aes=list(size=5)),
size = guide_legend(order =2),
fill = guide_colourbar(order=3),
color= guide_colourbar(order=4),
alpha= "none")
Veusz supports ternary plots. Here is an example from the documentation:
Chloƫ Lewis developed a triangle-plot general class, meant to support the soil texture triangle
with Python and Matplotlib. It's available here http://nature.berkeley.edu/~chlewis/Sourcecode.html https://github.com/chlewissoil/TernaryPlotPy
Chloe editing to add: Moved it to a more reliable host! Also, it's a public repo, so if you want to request library-ization, you could add an issue. Hope it's useful to someone.
I just discovered a tool which uses Python/Matplotlib to generate ternary plots called wxTernary. It's available via http://wxternary.sourceforge.net/ -- I was able to successfully generate a ternary plot on the first try.
There seems to be an implementation at work here in gnuplot:
(source: ugm.ac.id)
There is a R package named soiltexture. It's aimed at soil texture triangle plot, but can be customized for some aspects.
Find a vector drawing library and draw it from scratch if you can't find an easier way to do it.