Consider this simple example:
tibble(time = c(1,2,3,4,5),
var1 = c(2,2,2,2,1),
var2 = c(2,1,1,4,5)) %>%
barchart(var1 + var2 ~ time,
data = .,
stack = TRUE,
horiz = FALSE,
par.settings = simpleTheme(col = c('red', 'blue'),
fill = c('red', 'blue'),
alpha = c(0.2)),
auto.key = TRUE)
Despite my attempts, I was not able to set the alpha for the bars. They are way too bright! Is there a way to do so?
Thanks!
Just use rgb() for your colors, the fourth argument is alpha:
library(tidyverse)
library(lattice)
tibble(
time = c(1,2,3,4,5),
var1 = c(2,2,2,2,1),
var2 = c(2,1,1,4,5)) %>%
barchart(var1 + var2 ~ time, data = .,
stack = TRUE, horiz = FALSE,
par.settings =
simpleTheme(
col = c(
rgb(1,0,0,0.2),
rgb(0,0,1,0.2)),
fill = c(
rgb(1,0,0,0.2),
rgb(0,0,1,0.2))),
auto.key = TRUE)
The panel.barchart function for some reason completely ignores the alpha= parameter. #rg255's suggestion of changing the color is certainly the easiest way to fix this problem. You could also re-rewrite the panel function to actually use the alpha= option. It's a pretty messy function but I put the re-write in this gist: https://gist.github.com/MrFlick/d705d63075dd1d0c804be8e5543b9e72. If you load that function then you could just add
panel="panel.barchart.alpha"
to the call to barchart(). Unfortunately this messed up the auto key just a bit (it draws points rather than rectangles. But you could hack that back to the default by doing something like this
pp <- barchart(..., panel="panel.barchart.alpha")
pp$legend$top$args$points <- FALSE
pp$legend$top$args$rectangles <- TRUE
When specifying colours to R, you can use the hexadecimal format. In this format, you can add two numbers to the end that will relate to the degree of translucency you require. I'm not saying this is the best way of doing it, but it's how I achieve translucency in my core R plots.
e.g.
# Black points
plot(rnorm(10), rnorm(10), pch = 20, col = "#000000")
# Black points with 50% translucency
plot(rnorm(10), rnorm(10), pch = 20, col = "#00000050")
Related
I am creating a plot based on INLA predictions. Everything works perfectly for the modelling, but for the plot,the legend on the graph are points (like https://gis.stackexchange.com/questions/350918/how-do-i-reverse-spplot-colour-key-so-the-values-are-decreasing) rather than a scale (like here http://www.nickeubank.com/wp-content/uploads/2015/10/RGIS3_MakingMaps_part1_mappingVectorData.html):
And here is the code that I would like to change. I guess there is a problem of factor (R spplot: colorbar rather than legend for SpatialPoint data, spplot issue with legend range and colors distribution) but I cannot understand how/what to change:
m_grid <- inla(formWITHOUT, data = inla.stack.data(region.stack.predGrid, spde = inlaSetting$region.spde),
family = "gamma",
control.predictor = list(A = inla.stack.A(region.stack.predGrid), compute = TRUE, link=1),
control.compute = list(cpo = TRUE, dic = TRUE),
control.family=list(link="default"))
summary(m_grid)
index.pred <- inla.stack.index(region.stack.predGrid, "region.pred")$data
region.grid_sf$Sbiomass <- m_grid$summary.fitted.values[index.pred, "mean"]
region.grid_sf$Sbiomass_sd <- m_grid$summary.fitted.values[index.pred, "sd"]
my.palette <- brewer.pal(n = 7, name = "OrRd")
par(mar = c(0,0,0,0))
spplot(region.grid_sf, c("Sbiomass"), col.regions = my.palette, col = "transparent")
Thanks in advance for any tips !
I finally found the answer:
cuts <- c(0,5000,10000,15000,20000,25000,30000)
spplot(region.grid_sf,
c("Sbiomass"),
col.regions = my.palette,
col = "transparent",
key.space = list(x=0.1,y=0.3),
colorkey =T,
cuts = cuts,
cex = 2,
pch = 22)
I've been searching to find a solution, but none of the already existing questions fit my problem.
I have a data.frame:
Pat <- c(1,1,1,1,1,1,2,2,2,2,2,2)
V_ID <- c(1,1,6,6,9,9,1,1,6,6,9,9)
T_ID <- c("A","B","A","B","A","B","A","B","A","B", "A","B")
apples <- c(1,1,1,1,1,1,1,1,1,1,1,1)
bananas <- c(2,2,2,2,2,2,2,2,2,2,2,2)
cranberries <- c(3,3,3,3,3,3,3,3,3,3,3,3)
df <- data.frame(Pat,V_ID, T_ID, apples, bananas, cranberries)
I am trying to plot:
barplot(as.matrix(df[,4:6]) ,
main="tobefound", horiz = FALSE,width = 1,
names.arg=colnames(df[,4:6]),
las=2,
col = c("blue", "red"),
legend = df[,3],
args.legend = list(x="topleft"),
beside= FALSE)
BARPLOT
I need two changes:
First of all I like to have all "B"s (so the red part in every stack) piled up together and then the blue ones on top. Second: is there a way of decreasing the legend to only A and B once besides addressing this via
legend = df[1:2,3],
I am also looking for a solution using plotly or ggplot.
Thanks,
First reshape:
df_long <- tidyr::gather(df, 'key', 'value', apples:cranberries)
Then plot:
ggplot(df_long, aes(key, value, fill = T_ID)) + geom_col(col = 'black')
Or perhaps without the borders:
ggplot(df_long, aes(key, value, fill = T_ID)) + geom_col()
Using base graphics, you needed to sort df by T_ID first.
df = df[order(df$T_ID), ]
barplot(as.matrix(df[,4:6]) ,
main="tobefound", horiz = FALSE,width = 1,
names.arg=colnames(df[,4:6]),
las=2,
ylim = c(0,40),
col = 1+as.numeric(as.factor(df$T_ID)),
border = NA,
beside= FALSE)
box()
legend('topleft', fill = 1+as.numeric(as.factor(levels(df$T_ID))), legend = levels(as.factor(df$T_ID)))
I am using following commands to produce a scatterplot with jitter:
ddf = data.frame(NUMS = rnorm(500), GRP = sample(LETTERS[1:5],500,replace=T))
library(lattice)
stripplot(NUMS~GRP,data=ddf, jitter.data=T)
I want to add boxplots over these points (one for every group). I tried searching but I am not able to find code plotting all points (and not just outliers) and with jitter. How can I solve this. Thanks for your help.
Here's one way using base graphics.
boxplot(NUMS ~ GRP, data = ddf, lwd = 2, ylab = 'NUMS')
stripchart(NUMS ~ GRP, vertical = TRUE, data = ddf,
method = "jitter", add = TRUE, pch = 20, col = 'blue')
To do this in ggplot2, try:
ggplot(ddf, aes(x=GRP, y=NUMS)) +
geom_boxplot(outlier.shape=NA) + #avoid plotting outliers twice
geom_jitter(position=position_jitter(width=.1, height=0))
Obviously you can adjust the width and height arguments of position_jitter() to your liking (although I'd recommend height=0 since height jittering will make your plot inaccurate).
I've written an R function called spreadPoints() within a package basiclotteR. The package can be directly installed into your R library using the following code:
install.packages("devtools")
library("devtools")
install_github("JosephCrispell/basicPlotteR")
For the example provided, I used the following code to generate the example figure below.
ddf = data.frame(NUMS = rnorm(500), GRP = sample(LETTERS[1:5],500,replace=T))
boxplot(NUMS ~ GRP, data = ddf, lwd = 2, ylab = 'NUMS')
spreadPointsMultiple(data=ddf, responseColumn="NUMS", categoriesColumn="GRP",
col="blue", plotOutliers=TRUE)
It is a work in progress (the lack of formula as input is clunky!) but it provides a non-random method to spread points on the X axis that doubles as a violin like summary of the data. Take a look at the source code, if you're interested.
For a lattice solution:
library(lattice)
ddf = data.frame(NUMS = rnorm(500), GRP = sample(LETTERS[1:5], 500, replace = T))
bwplot(NUMS ~ GRP, ddf, panel = function(...) {
panel.bwplot(..., pch = "|")
panel.xyplot(..., jitter.x = TRUE)})
The default median dot symbol was changed to a line with pch = "|". Other properties of the box and whiskers can be adjusted with box.umbrella and box.rectangle through the trellis.par.set() function. The amount of jitter can be adjusted through a variable named factor where factor = 1.5 increases it by 50%.
for instance when i got this:
http://i.stack.imgur.com/cWTIm.jpg
It seems that I've to set the color for every outlier separately...
Here is my (fractional) guess at code:
...,par.settings = list(...,box.rectangle = list(col= c("red","blue")),...) ),...
thx already in advance!
Fair question, but please do not post "fractional guesses at code"; it's unfair to ask other to generate the sample problem.
Here is the sample code, which confirms what you found:
library(lattice)
d = data.frame(x=c(rnorm(90),20*runif(16)),group=letters[1:2])
cols = list(col=c("red","blue"),pch=c(1,16,13))
bwplot(group~x,data=d,
par.settings = list(
plot.symbol=cols,
box.rectangle = cols,
box.dot = cols,
box.umbrella=cols
))
and here is the code that shows that the outlier pch/col/alpha/cex are not grouped, and therefore are recycled incorrectly.
From panel.bwplot:
panel.points(x = rep(levels.fos, sapply(blist.out, length)),
y = unlist(blist.out), pch = plot.symbol$pch, col = plot.symbol$col,
alpha = plot.symbol$alpha, cex = plot.symbol$cex,
fontfamily = plot.symbol$fontfamily, ......
Which means that this is a missing feature in lattice (I would not call it a bug).
I would like to overlay 2 density plots on the same device with R. How can I do that? I searched the web but I didn't find any obvious solution.
My idea would be to read data from a text file (columns) and then use
plot(density(MyData$Column1))
plot(density(MyData$Column2), add=T)
Or something in this spirit.
use lines for the second one:
plot(density(MyData$Column1))
lines(density(MyData$Column2))
make sure the limits of the first plot are suitable, though.
ggplot2 is another graphics package that handles things like the range issue Gavin mentions in a pretty slick way. It also handles auto generating appropriate legends and just generally has a more polished feel in my opinion out of the box with less manual manipulation.
library(ggplot2)
#Sample data
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
, lines = rep(c("a", "b"), each = 100))
#Plot.
ggplot(dat, aes(x = dens, fill = lines)) + geom_density(alpha = 0.5)
Adding base graphics version that takes care of y-axis limits, add colors and works for any number of columns:
If we have a data set:
myData <- data.frame(std.nromal=rnorm(1000, m=0, sd=1),
wide.normal=rnorm(1000, m=0, sd=2),
exponent=rexp(1000, rate=1),
uniform=runif(1000, min=-3, max=3)
)
Then to plot the densities:
dens <- apply(myData, 2, density)
plot(NA, xlim=range(sapply(dens, "[", "x")), ylim=range(sapply(dens, "[", "y")))
mapply(lines, dens, col=1:length(dens))
legend("topright", legend=names(dens), fill=1:length(dens))
Which gives:
Just to provide a complete set, here's a version of Chase's answer using lattice:
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
, lines = rep(c("a", "b"), each = 100))
densityplot(~dens,data=dat,groups = lines,
plot.points = FALSE, ref = TRUE,
auto.key = list(space = "right"))
which produces a plot like this:
That's how I do it in base (it's actually mentionned in the first answer comments but I'll show the full code here, including legend as I can not comment yet...)
First you need to get the info on the max values for the y axis from the density plots. So you need to actually compute the densities separately first
dta_A <- density(VarA, na.rm = TRUE)
dta_B <- density(VarB, na.rm = TRUE)
Then plot them according to the first answer and define min and max values for the y axis that you just got. (I set the min value to 0)
plot(dta_A, col = "blue", main = "2 densities on one plot"),
ylim = c(0, max(dta_A$y,dta_B$y)))
lines(dta_B, col = "red")
Then add a legend to the top right corner
legend("topright", c("VarA","VarB"), lty = c(1,1), col = c("blue","red"))
I took the above lattice example and made a nifty function. There is probably a better way to do this with reshape via melt/cast. (Comment or edit if you see an improvement.)
multi.density.plot=function(data,main=paste(names(data),collapse = ' vs '),...){
##combines multiple density plots together when given a list
df=data.frame();
for(n in names(data)){
idf=data.frame(x=data[[n]],label=rep(n,length(data[[n]])))
df=rbind(df,idf)
}
densityplot(~x,data=df,groups = label,plot.points = F, ref = T, auto.key = list(space = "right"),main=main,...)
}
Example usage:
multi.density.plot(list(BN1=bn1$V1,BN2=bn2$V1),main='BN1 vs BN2')
multi.density.plot(list(BN1=bn1$V1,BN2=bn2$V1))
You can use the ggjoy package. Let's say that we have three different beta distributions such as:
set.seed(5)
b1<-data.frame(Variant= "Variant 1", Values = rbeta(1000, 101, 1001))
b2<-data.frame(Variant= "Variant 2", Values = rbeta(1000, 111, 1011))
b3<-data.frame(Variant= "Variant 3", Values = rbeta(1000, 11, 101))
df<-rbind(b1,b2,b3)
You can get the three different distributions as follows:
library(tidyverse)
library(ggjoy)
ggplot(df, aes(x=Values, y=Variant))+
geom_joy(scale = 2, alpha=0.5) +
scale_y_discrete(expand=c(0.01, 0)) +
scale_x_continuous(expand=c(0.01, 0)) +
theme_joy()
Whenever there are issues of mismatched axis limits, the right tool in base graphics is to use matplot. The key is to leverage the from and to arguments to density.default. It's a bit hackish, but fairly straightforward to roll yourself:
set.seed(102349)
x1 = rnorm(1000, mean = 5, sd = 3)
x2 = rnorm(5000, mean = 2, sd = 8)
xrng = range(x1, x2)
#force the x values at which density is
# evaluated to be the same between 'density'
# calls by specifying 'from' and 'to'
# (and possibly 'n', if you'd like)
kde1 = density(x1, from = xrng[1L], to = xrng[2L])
kde2 = density(x2, from = xrng[1L], to = xrng[2L])
matplot(kde1$x, cbind(kde1$y, kde2$y))
Add bells and whistles as desired (matplot accepts all the standard plot/par arguments, e.g. lty, type, col, lwd, ...).