Creating a reactive rectangular plot - r

I am relatively new to R. I am making an R Shiny app, and based on the input of the user, I would like to analyze the data and output a bar that shows the Jaccard index. This is what I want it to look like, although obviously a smooth gradient:
Please note that the Jaccard index (in this case, 0.35) will change after each input, so I'd like something reactive. I just have no idea where to start or if making plots like this is even possible in R.
Thanks.
edit: I used an online gradient generator to come up with this plot instead: how could I overlay a vertical line with its corresponding Jaccard index and corresponding location on the bar on this particular image?
edit: I want to remove the white space before the actual plot and after my text. any ideas?

With the plotrix package:
library(plotrix)
# get an empty box
plot(0:10, type="n", axes=FALSE, xlab=NA, ylab=NA)
# rectangle filled with a gradient
gradient.rect(0, 0, 10, 5, col=smoothColors("red",38,"blue"), border=NA)
# vertical bar
segments(3.5, 0, 3.5, 5, lwd=2)
text(3.5, 0, "0.35", pos=1, xpd=TRUE)

For something in base R, an imperfectly modified version of this solution, might work.
color.bar <- function(lut, min, max=-min, nticks=11, ticks=seq(min, max, len=nticks), title='') {
scale = (length(lut)-1)/(max-min)
dev.new(width=1.75, height=5)
plot(c(min,max), c(0,10), type='n', bty='n', xaxt='n', xlab='', yaxt='n', ylab='', main=title)
for (i in 1:(length(lut)-3)) {
x = (i-1)/scale + min
rect(x, 0 ,1, 30/scale, col=lut[i], border=NA)
}
}
Then make the graph as follows -
color.bar(colorRampPalette(c("light green", "yellow", "orange", "red"))(100), 0, 1)
At this point perhaps you can add an abline(v = 0.35) to get what you want?
You could even try pointing to the appropriate position using an arrow using
arrows(0.35, -1, 0.35, 0, length = 0.07, angle = 25)

Related

Can't get axis labels to show on r plot()

I'm working with the meuse dataset in the sp library in R and I'm just trying to obtain a simple plot of the meuse grid which highlights the different areas of flooding frequency. However, I can't seem to get the axis labels to display. I've tried using a par() statement beforehand but it doesn't appear to be doing anything?
data(meuse.grid) #in sp library
summary(meuse.grid)
str(meuse.grid)
coordinates(meuse.grid) = ~x+y
proj4string(meuse.grid)<-CRS("+init=epsg:28992")
gridded(meuse.grid)=TRUE
class(meuse.grid)
par(mar=c(10,10,4,2)+0.1,mgp=c(5,1,0))
plot(meuse.grid["ffreq"], scale.frac = 0.6,main="Flooding Frequency Class Map",
xlab="Easting",ylab="Northing",axes=TRUE)
Any suggestions?
You could use mtext as a fix, expand slightly outer margins oma in advance. You could also fix the title with this method.
par(mar=c(10,10,4,2) + 0.1, mgp=c(5,1,0), oma=c(2, 2, 2, 2))
plot(meuse.grid["ffreq"], scale.frac = 0.6,main="",
xlab="",ylab="",axes=TRUE)
mtext("Easting", side=1, line=3, font=2)
mtext("Northing", side=2, line=3, font=2)
mtext("Flooding Frequency Class Map", side=3, line=1, font=2, cex=1.2)
Try reducing the plot margins by setting par() before your plot() function. The default values are:
par(mar = c(5, 4, 4, 2) + 0.1)
where each number represents a side of the plot (bottom, left, top, right). setting the outer margins via par(oma) (in a similar way to above) might also help.

Histogram chart getting cut when using package plot3D

I'm trying to plot a simple histogram using hist3D() from plot3D package using the following code:
library(tidyverse)
library(plot3D)
data(iris)
iris=as.tibble(iris)
x=c(1,2)
y=x
z=matrix(rnorm(4,sd=0.5,mean=1),ncol=2,nrow=2)
pmat<-hist3D(x,y,
z,
border="black",
axes=TRUE,
expand=0.4,
theta=40,phi=30,
zmin=-1,
margin=c(10,10),
mar=c(10, 1, 0, 2),
ticktype = "detailed",col="green",box=TRUE)
But the histogram get cut at the bottom:
So, I'm looking for a way to extends the width or the height of the canvas for hist3D().
You can use par(xpd = NA) before the hist3D call to allow your full device region to be used for plotting. This might not be enough space; if not, set the margins to be really large as well. For example,
par(xpd = NA, mar = c(10,10,10,10))
hist3D(x,y,
z,
border="black",
axes=TRUE,
expand=0.4,
theta=40,phi=30,
zmin=-1,
margin=c(20,20),
mar=c(10, 1, 0, 2),
ticktype = "detailed",col="green",box=TRUE)
produces this for me:
It's pretty ugly, but that's to be expected for a 3D histogram :-).

Add second barplot to existing one manually (using add=T)

Is there a way in base R to manually add a second barplot to an existing one. I know how to do it if the two series are from the same data object (using barplot( ... beside=T)) or I guess one could draw rectangles (rect(...)) which barplot wraps. If your data is from different objects how can you then do it with the barplot function ? How to control bar positions?
I tried this using the space parameter (obviously not working):
h1 <- c(10,5,1)
h2 <- c(8, 3, 1)
barplot(h1, width = 0.5, space = 2, col='red')
barplot(h2, width = 0.5, space = 2.5, col='blue', add=T)
It is impossible to get the bars besides each other as when using the beside=T argument.
Desired output is something along this:
barplot(matrix(c(h1, h2), nrow=2, byrow=T), beside=T, col=c('red', 'blue'))
UPDATE: how it works
In order for me to finally - I hope - understand the width and space arguments, we can plot an axis and play with the parameters for the blue data.
barplot(h1, width = 0.5, space = 2, col='red')
axis(1, seq(0, 10, 0.5)) #way out of the plot region
barplot(h2, width = 0.25, space = c(4,2,4), col='blue', add=T)
From this it seem as (correct me if I am wrong):
1. width is the width of each bar - recycled as necessary
2. space controls the space to the previous bar (to the left) or to 0 for the first bar, and is calculated as width*space for the current bar - recycled as necessary. So the first blue bar starts at (space to 0) 0.25*4 = 1 and its right side is at 1+0.25 = 1.25; the second bar starts at 1.25+0.25*2 = 1.75, and its right side is at 1.75+0.25 = 2. And so forth...
You can do this:
h1 <- c(10,5,1)
h2 <- c(8, 3, 1)
barplot(h1, width = 0.5, space = 2, col='red')
barplot(h2, width = 0.5, space = c(3,2,2), col='blue', add=T)
And this will be the output:

Techniques to get a meticulous polygon in R

Background:
I have a polygon() that doesn't look as professional as I need it to be (see my R code blow).
I usually use two general techniques to make ploygon()s come out the way I want them to be. First, in my curve, I use lwd = larger than 1. Second, in my polygon, I remove the border of my polygon() by border = NA.
In this case below, for some reasons, I can NOT use the first technique.
Question:
I was wondering what else I can do in addition to removing the border=NA in my polygon() to improve my polygon?
curve(dnorm(x), -3, 3, bty="n", ann=F, axes=F, col="blue")
xs <- seq(-0.5, 0.5, len=1000)
polygon(c(xs[1], xs, xs[1000]), c(0, dnorm(xs), 0), col='grey', border = NA)
I don't know how much better this is, but maybe add curve after the polygon
curve(dnorm(x), -3, 3, bty="n", ann=F, axes=F, col=NA)
xs <- seq(-0.5, 0.5, len=1000)
polygon(c(xs[1], xs, xs[1000]), c(0, dnorm(xs), 0), col='grey', border = NA)
curve(dnorm(x), -3, 3, col='blue', add = TRUE, n = 1e4)
#n = 1e4 helps plot curve with more points (default in 101), making it smoother

Plot average of values in single plot

I want to plot single bar in a graph so it would look like picture below
I created test data and calculate its mean.
value <- c(99,44,100,120,88)
value_mean <- mean(value)
And plot them using below code
barplot(value_mean, horiz=T, width=30, cex.names=0.5 ,ylim=c(0,200), col="red")
Buth the output is not even close.
I've also looked at this links
Single bar barchart in ggplot2, R
R Barplot with one bar - how to plot correctly
So my output should be something like the first picture. I was thinking that could solve ggplot.
If everything else fails, you can draw a rectangle like this:
par(mar = c(12, 2, 12, 2))
plot(0, type="n", ylim=c(-1, 1), xlim=c(0, 200), axes = F, bty = "n",ylab="", xlab="label")
rect(0, -.7, value_mean, .7, col="red", border=NA)
text(value_mean, 0, pos=4, label=value_mean)
axis(1, at=seq(0, 200, by=40))

Resources