I want to make a plot that is similar to beanplot or violin plot, but instead of the symmetric shapes, i want to plot two different distributions on the different sides of the center line. Something like figure 4 in this article [pdf]http://www.jstatsoft.org/v28/c01/paper.
I want to use the grid graphics engine in R. Any pointers will be useful. I looked at the lattice package and the histogram function in lattice package, but that is not what i want to do.
Any help/pointers are appreciated.
You can reasonably easily get the half-violin plot with fairly simple modifications to the function, panel.violin in Sarkar's lattice package. There are four lines in that function that can be altered inside the grid.polygon call to change from "two-sided" density plotting to single sided density plotting. First require(lattice) and require(grid). Then type panel.violin. I'll show you the "horizontal" alteration:
require(grid)
panel.violin2 <-
# snipped all the arguments and processing
grid.polygon(x = c(dx.list[[i]] ),
# Notice I removed: ... ,rev(dx.list[[i]])
y = c(2*dy.list[[i]] ), default.units = "native",
# Removed: ... , -rev(dy.list[[i]])
name = trellis.grobname(identifier, type = "panel",
group = group), gp = gpar(fill = col, col = border,
lty = lty, lwd = lwd, alpha = alpha))
Also remove it from the corresponding section in the else{ ...} clause. Now you can run it with the example in help(panel.violin)
bwplot(voice.part ~ height, singer,
panel = function(..., box.ratio) {
panel.violin2(..., col = "transparent",
varwidth = FALSE, box.ratio = box.ratio)
panel.bwplot(..., fill = NULL, box.ratio = .1)
} )
If you wanted the density on the other side, all you would need to do would be remove the dx.list[[i]] and dy.list[[i]] and leave in the rev(dx.list[[i]]) and -rev(dy.list[[i]]).
Related
I am trying to plot a likert scale of a 1 - 7 scale for every country with the likert package in R, but the R base plot() function won't change any of the text sizes (or even add a main title).
I am generating the plot with:
p <- likert(summary = data )
plot(p,
plot.percents=FALSE,
plot.percent.low=FALSE,
plot.percent.high=FALSE,
include.center=TRUE,
plot.percent.neutral = FALSE,
col = c(brewer.pal(n = 7, name = "RdBu")),
cex.axis = 0.5,
cex.lab=0.5,
main = "title")
Which produces the following plot:
Plot of Countries of the World
All the other plot parameters are working, so I'm not sure why the last 3, the most basic aren't working.
I fixed this by using theme(axis.text) like so:
plot(p,
plot.percents=FALSE,
plot.percent.low=FALSE,
plot.percent.high=FALSE,
include.center=TRUE,
plot.percent.neutral = FALSE,
col = c(brewer.pal(n = 7, name = "RdBu")),
main = "title") +
theme(axis.text=element_text(size=4)
This doesn't answer the larger question as to why the plot() function isn't accepting the parameters, as the title still isn't showing, but it's a band aid solution
I am making a series of plots from a point pattern (PPP) with the density (kernel) function. I would like that the maximum plotted number is 200 in all cases and just the heatmap accordingly (two of the images only go up to 100). I have not been able to find a solution to this problem using the R base plot.
Microglia_Density <- density(Microglia_PPP, sigma =0.1, equal.ribbon = TRUE, col = topo.colors, main = "")
plot(Microglia_Density, main = "Microglia density")
Astrocytes_Density <- density(Astrocytes_PPP, sigma =0.1, equal.ribbon = TRUE, col = topo.colors, main = "")
plot(Astrocytes_Density, main = "Astrocytes density")
Neurons_Density <- density(Neurons_PPP, sigma =0.1, equal.ribbon = TRUE, col = topo.colors, main = "")
plot(Neurons_Density, main = "Neuronal density")
I would appreciate recommendations. Regards
Since we don’t have access to your data I simulate fake data in a square.
There are several options to do what you want. First you should know that
density() is a generic function, so when you invoke it on a ppp like
Microglia_PPP actually the function density.ppp() is invoked.
This function returns an im object (effectively a 2-d “image” of values).
You plot this with plot() which in turn calls plot.im(), so you should
read the help file of plot.im(), where it says that the argument col
controls the colours used in the plot. Either you can make a colour map
covering the range of values you are interested in and supply that, or if you
know that one of the images has the colour map you want to use you can save
it and reuse for the others:
library(spatstat)
set.seed(42)
Microglia_PPP <- runifpoint(100)
Neurons_PPP <- runifpoint(200)
Neurons_Density <- density(Neurons_PPP, sigma = 0.1)
Microglia_Density <- density(Microglia_PPP, sigma = 0.1)
my_colourmap <- plot(Neurons_Density, main = "Neuronal density", col = topo.colors)
plot(Microglia_Density, main = "Microglia density", col = my_colourmap)
Notice the colour maps are the same, but it only covers the range from
approximately 80 to 310. Any values of the image outside this range will not
be plottet, so they appear white.
You can make a colour map first and then use it for all the plots
(see help(colourmap)):
my_colourmap <- colourmap(topo.colors(256), range = c(40,315))
plot(Neurons_Density, main = "Neuronal density", col = my_colourmap)
plot(Microglia_Density, main = "Microglia density", col = my_colourmap)
Finally another solution if you want the images side by side is to make them
an imlist (image list) and use plot.imlist() with equal.ribbon = TRUE:
density_list <- as.imlist(list(Neurons_Density, Microglia_Density))
plot(density_list, equal.ribbon = TRUE, main = "")
The partykit package plots barplots at the terminal nodes of trees which gives a visual rendition of the posterior probabilities of the dependent variable classes.
I would like to add those barplots also in the inner nodes, below the standard circles/ellipses. This needs to use a function that is a mixture of node_inner() and node_barplot() to the inner_panel argument of the plot() method.
But those function have pretty complex internals and I'm not sure how to mix the two in order to have to inner plots stacked vertically.
Any ideas?
It's possible, it just doesn't look very appealing. If you want to show the name of the splitting variable and the p-value, it would be better to tweak the mainlab argument of node_barplot. In the answer to
Ctree classification with weights - results displayed there is in illustration how to include weights in the title - in a similar fashion you could display splitting variable and p-value.
If you are determined to set up a new panel function that has two subpanels, you need a little bit of grid programming (the graphics system that the plot() method is based on). You need to set up a grid.layout and then go through the resulting viewports.
make_inner_and_barplot <- function(object, ...) {
function(node) {
## layout
pushViewport(viewport(layout = grid.layout(nrow = 2, ncol = 1,
heights = unit(c(0.2, 0.8), "npc"))))
## background color
grid.rect(gp = gpar(fill = "white", col = 0))
## circle
pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1))
node_inner(object)(node)
popViewport()
## circle
pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2))
node_barplot(object, id = FALSE, ...)(node)
popViewport(2)
}
}
With the resulting panel function you can then do:
ct <- ctree(factor(cyl) ~ ., data = mtcars, minsplit = 2)
plot(ct, inner_panel = make_inner_and_barplot(ct), tnex = 0.8)
I've got the results of clustering and decided to make a boxplot for each cluster, using lattice.
Next, I was faced with the need to establish a scale, acceptable to all cluster boxplots.
Found a solution, which allows to exclude an outliers and set free relation.
library(lattice)
trellis.device(new=FALSE, col=FALSE)
bwplot(value ~ variable | Cluster, data = test,
layout = c(2,2),
prepanel = function(x, y) {
bp <- boxplot(split(y, x), plot = FALSE)
ylim <- range(bp$stats)
list(ylim = ylim) },
scales = list(y = list(relation = "free")),
do.out = F)
So, I've got pretty good plots, but it can be better, if I manually set the ylim for each plot. Eg there is only integer values in my data and the value 0.5 at upper left cluster graph is meaningless.
So, is there any way to set multiple ylims in bwplot parameters?
From the documentation under ?bwplot:
xlim could also be a list, with as many components as the number of panels (recycled if necessary), with each component as described above. This is meaningful only when scales$x$relation is "free", in which case these are treated as if they were the corresponding limit components returned by prepanel calculations.
The ylim argument has the corresponding functionality for the y-axis.
So, set relation = "free" in the scales argument as you did, and then pass a list to the ylim argument to individually set the y-axis limits for each panel:
bwplot(len ~ factor(dose) | supp, data = ToothGrowth,
scales = list(relation = "free"),
ylim = list(c(5, 31), c(0, 36)))
At first I thought this would be trivial, but I could not figure out how to combine rectangles with lines in the legend of a lattice plot. Consider the following example:
library(latticeExtra)
xyplot(rnorm(10) ~ 1:10,
key=list(rectangles=list(size=2, border=F),
text=list(c("Zero", "One", "Two"), col="black"),
col=c("black", "lightgrey", "darkgrey"), divide=1, columns=1,
x=0.01, y=0.95, corner=c(0,1) ),
panel=function(x,...){
panel.abline(v=3, lty="dashed")
panel.xblocks(x,x>5, col="lightgrey")
panel.xblocks(x,x>7, col="darkgrey")
panel.xyplot(x, ...) } )
Instead of 3 rectangles, I would like to have 2 rectangles filled with the appropriate colours, and one dashed line above or below these two rectangles. If I provide a lines argument, then both lines and rectangles will be drawn for all elements (i.e. there will be 2 rectangles and 2 lines simultaneously next to each other).
How can I set up the legend key so that I get this mix of "symbols"? That is, how can I get one dashed line and two rectangles with the appropriate text and colours?
Any help is greatly appreciated! My apologies if this is trival. Please help me see the obvious! :)
This is a rather late answer but it is something I still do. One approach is to use auto.key in the function and then modify the lattice object with update(obj, key = newKey). A more general approach, as suggested by #josh-obrien, is to use the grid functions that under lattice. However, this typically requires empirical tweaking of the coordinates as can be seen in the need to use 3 decimal places of precision to place the dashed lines.
# relative position may be sensitive to absolute sizes
library(latticeExtra)
dev.new(width = 5, height = 5)
set.seed(1234)
# same code as in question, re-written a little bit
# using "transparent" for the 1st of the three rectangles
# using a grid call in the panel function to place the dashed line
xyplot(rnorm(10) ~ 1:10,
key = list(rectangles = list(size = 2, border = FALSE,
col = c("transparent", "lightgrey", "darkgrey")),
text = list(c("Zero", "One", "Two"), col = "black"),
columns = 1, corner = c(0.01, 0.95)),
panel = function(x,...) {
panel.abline(v = 3, lty = "dashed")
panel.xblocks(x, x > 5, col = "lightgrey")
panel.xblocks(x, x > 7, col = "darkgrey")
panel.xyplot(x, ...)
grid::grid.lines(c(0.04, 0.07), c(0.935, 0.935),
gp = gpar(lty = "dashed", col = "black"))
}
)
[![plot with combined elements in legend][1]][1]
[1]: https://i.stack.imgur.com/K7AJN.png