How to draw a density heat map on Ternary plot in R? - r

Heads up I am an R noob so bare with please!
I am trying to identify areas where the most data points are situated using a density heatmap.
Here is what the plot looks like
What will I have to add to this code I've done so far (I listed less data points obviously) to apply this 'heatmap'?
par(mfrow=c(1, 2), mar=rep(0.3, 4))
TernaryPlot(atip = "Red", btip = "Green", ctip = "Blue", alab="Redder\u2192", blab="Greener \u2192", clab="Bluer \u2190",
point='Up', lab.cex=0.8, grid.minor.lines = 0,
grid.lty='solid', col=rgb(0.9,0.9,0.9), grid.col='White',
axis.col=rgb(0, 0, 0), ticks.col=rgb(0, 0, 0),
padding=0.08)
data_points <- list(
c(0.89,0.88,0.78),
c(0.98,0.96,0.92),
c(0.6,0.52,0.28),
c(0.88,0.9,0.85),
c(0.96,0.87,0.6),
c(0.63,0.53,0.29),
c(0.92,0.85,0.09),
c(0.84,0.87,0.87),
c(0.93,0.88,0.88),
c(0.98,0.76,0.71)
)
AddToTernary(points, data_points, bg=vapply(data_points, function (x) rgb(x[1], x[2], x[3], 1, maxColorValue=1), character(1)), pch=25, cex=0.8)
AddToTernary(text, data_points, names(data_points), cex=0.8, font=2)
Sorry for being so silly, very new to all this, learning lots thanks to this website!

The TernaryPlot function from the Ternary package creates and styles a blank Ternary plot. If you would like to show your data points, you need to use the TernaryPoints function:
TernaryPlot(atip = "Red", btip = "Green", ctip = "Blue", alab="Redder\u2192", blab="Greener \u2192", clab="Bluer \u2190",
point='Up', lab.cex=0.8, grid.minor.lines = 0,
grid.lty='solid', col=rgb(0.9,0.9,0.9), grid.col='White',
axis.col=rgb(0, 0, 0), ticks.col=rgb(0, 0, 0),
padding=0.08)
TernaryPoints(data_points)
You will get the following plot:
Another option is to use the vcd library:
library(vcd)
# convert data points into a matrix
data_points = matrix(unlist(data_points), ncol=3, byrow=T)
ternaryplot(x=data_points)
Using vcd, you should get the following plot:

Related

How to draw a regression formula in R? [duplicate]

What are the alternatives for drawing a simple curve for a function like
eq = function(x){x*x}
in R?
It sounds such an obvious question, but I could only find these related questions on stackoverflow, but they are all more specific
Plot line function in R
Plotting functions on top of datapoints in R
How can I plot a function in R with complex numbers?
How to plot a simple piecewise linear function?
Draw more than one function curves in the same plot
I hope I didn't write a duplicate question.
I did some searching on the web, and this are some ways that I found:
The easiest way is using curve without predefined function
curve(x^2, from=1, to=50, , xlab="x", ylab="y")
You can also use curve when you have a predfined function
eq = function(x){x*x}
curve(eq, from=1, to=50, xlab="x", ylab="y")
If you want to use ggplot,
library("ggplot2")
eq = function(x){x*x}
ggplot(data.frame(x=c(1, 50)), aes(x=x)) +
stat_function(fun=eq)
You mean like this?
> eq = function(x){x*x}
> plot(eq(1:1000), type='l')
(Or whatever range of values is relevant to your function)
plot has a plot.function method
plot(eq, 1, 1000)
Or
curve(eq, 1, 1000)
Here is a lattice version:
library(lattice)
eq<-function(x) {x*x}
X<-1:1000
xyplot(eq(X)~X,type="l")
Lattice solution with additional settings which I needed:
library(lattice)
distribution<-function(x) {2^(-x*2)}
X<-seq(0,10,0.00001)
xyplot(distribution(X)~X,type="l", col = rgb(red = 255, green = 90, blue = 0, maxColorValue = 255), cex.lab = 3.5, cex.axis = 3.5, lwd=2 )
If you need your range of values for x plotted in increments different from 1, e.g. 0.00001 you can use:
X<-seq(0,10,0.00001)
You can change the colour of your line by defining a rgb value:
col = rgb(red = 255, green = 90, blue = 0, maxColorValue = 255)
You can change the width of the plotted line by setting:
lwd = 2
You can change the size of the labels by scaling them:
cex.lab = 3.5, cex.axis = 3.5
As sjdh also mentioned, ggplot2 comes to the rescue. A more intuitive way without making a dummy data set is to use xlim:
library(ggplot2)
eq <- function(x){sin(x)}
base <- ggplot() + xlim(0, 30)
base + geom_function(fun=eq)
Additionally, for a smoother graph we can set the number of points over which the graph is interpolated using n:
base + geom_function(fun=eq, n=10000)
Function containing parameters
I had a function (emax()) involving 3 parameters (a, b & h) whose line I wanted to plot:
emax = function(x, a, b, h){
(a * x^h)/(b + x^h)
}
curve(emax, from = 1, to = 40, n=40 a = 1, b = 2, h = 3)
which errored with Error in emax(x) : argument "a" is missing, with no default error.
This is fixed by putting the named arguments within the function using this syntax:
curve(emax(x, a = 1, b = 2, h = 3), from = 1, to = 40, n = 40)
which is contrary to the documentation which writes curve(expr, from, to, n, ...) rather than curve(expr(x,...), from, to, n).

Customize breaks on a color gradient legend using base R

Here is a sample script using random numbers instead of real elevation data.
library(gridExtra)
library(spatstat) #im function
elevation <- runif(500, 0, 10)
B <- matrix(elevation, nrow = 20, ncol = 25)
Elevation_Map <- im(B)
custom <- colorRampPalette(c("cyan","green", "yellow", "orange", "red"))
plot(Elevation_Map, col = custom(10), main = NULL)
This is the plot and legend that I get:
This is the legend that I am trying to recreate in R (this one made in Word):
I know this is possible and its probably a simple solution but I've tried using some examples I found online to no avail.
This plot (with real elevation data) is an art piece that will be hung in a gallery, with the elevation plot on 1 board and the legend on a separate board. I tried to get R to plot just the plot without the legend using
plot(Elevation_Map, col = custom(10), main = NULL, legend = NULL)
like I have in the past but for some reason it always plots the legend with the plot. As of right now I'm planning on just cropping the .pdf into 2 separate files to achieve this.
Here are two ways of doing it using other packages:
# example data, set seed to reproduce.
set.seed(1); elevation <- runif(500, 0, 10)
B <- matrix(elevation, nrow = 20, ncol = 25)
#Elevation_Map <- im(B)
custom <- colorRampPalette(c("cyan","green", "yellow", "orange", "red"))
1) Using fields package, image.plot(), it is same "base" graphics::image.default() plot but with more arguments for customisation (but couldn't remove the ticks from legend):
library(fields)
image.plot(B, nlevel = 10, col = custom(10),
breaks = 1:11,
lab.breaks = c("Low Elevation", rep("", 9), "High Elevation"),
legend.mar = 10)
2) Using ggplot package, geom_raster function:
library(ggplot2)
library(reshape) # convert matrix to long dataframe: melt
B_melt <- reshape2::melt(B)
head(B_melt)
ggplot(B_melt, aes(X1, X2, fill = value)) +
geom_raster() +
theme_void() +
scale_fill_gradientn(name = element_blank(),
breaks = c(1, 9),
labels = c("Low Elevation", "High Elevation"),
colours = custom(10))
The code in the original post is using the im class from the spatstat package. The plot command is dispatched to plot.im. Simply look at help(plot.im) to figure out how to control the colour ribbon. The relevant argument is ribargs. Here is a solution:
plot(Elevation_Map, col=custom(10), main="",
ribargs=list(at=Elevation_Map$yrange,
labels=c("Low Elevation", "High Elevation"),
las=1))

R: drawing multiple things over one another

I have a data table and I want to do the following:
1) use xyplot to plot the data
2) use rasterimage to 'mark' certain regions in this plot as 'good' (green) or 'bad' (red)
This is what I got so far:
library(lattice)
dataFrame = data.frame(
Z1 = c(0, 1, 2, 3, 4),
Z2 = c(0, 1, 2, 3, 4))
dataFrameResult = data.frame(
install=c(TRUE, TRUE, FALSE))
imageMatrix = matrix(
c(rgb(255, 0, 0, alpha=100, maxColorValue = 255 ),rgb(0, 255, 0, alpha=100, maxColorValue = 255 ),
rgb(255, 0, 0, alpha=100, maxColorValue = 255 ),rgb(0, 0, 255, alpha=100, maxColorValue = 255 )),
nrow = 2, ncol = 2, byrow = TRUE,)
image <- as.raster(imageMatrix)
fig = xyplot(Z1 ~ Z2, group = dataFrameResult$install, data=dataFrame)
plot.new()
print(fig, pos=c(0,0,1,1), more = TRUE)
par(new=TRUE)
plot(c(0, 3), c(0, 3), type = "n", xlab = "", ylab = "")
rasterImage(image, 0, 0, 1, 1, interpolate = FALSE)
This produces the following:
In principal it looks fine but the positioning of the rasterImage function and the positioning of the xyplot do not match up... So, instead of guessing and pushing them around (does this procedure depend on the scales, etc.?) I thought that it can't be that hard to draw an image into a plot... right?
So anybody knows how to achieve the image below with (0,0) being (0,0) in and (1,1) being (1,1) in both scales? Or, even better, is there a way to draw an xyplot and tell R to paint the background in a user specified function like so...
getColor = function(x,y) {
return(rgb(x, y, 0, 0, ...))
}
plot (backgroundColorFunction=getColor)
Cheers,
FW
an easier way is to use the normal plot function, and use the functions like rect() after your plot to mark the regions and points() to plot the data,
for example :
> plot(c(1, 5), c(0, 4), type= "n", xlab = "", ylab ="")
> rect( 2 ,3 , 3 , 4 , col ="green" , border="red" )
> points(c(1:5),c(0:4),col="blue")
> rect(1.8,2.8,2.3,3.4,col="white",border = "white")
that results :
you can customize your plot by changing the parameters and using your data inside this function. other functions to use after plot are :
plot.default, plot.window, points, lines, abline, axis, title, text, mtext, segments, symbols, arrows, polygon, rect, box, contour, filled.contour and image.
try search them in R help, easy to use :)
I've to mention that you can use this function for many times for one plot for example if you want to plot 2 rects just write two rect() function

How to plot a function curve in R

What are the alternatives for drawing a simple curve for a function like
eq = function(x){x*x}
in R?
It sounds such an obvious question, but I could only find these related questions on stackoverflow, but they are all more specific
Plot line function in R
Plotting functions on top of datapoints in R
How can I plot a function in R with complex numbers?
How to plot a simple piecewise linear function?
Draw more than one function curves in the same plot
I hope I didn't write a duplicate question.
I did some searching on the web, and this are some ways that I found:
The easiest way is using curve without predefined function
curve(x^2, from=1, to=50, , xlab="x", ylab="y")
You can also use curve when you have a predfined function
eq = function(x){x*x}
curve(eq, from=1, to=50, xlab="x", ylab="y")
If you want to use ggplot,
library("ggplot2")
eq = function(x){x*x}
ggplot(data.frame(x=c(1, 50)), aes(x=x)) +
stat_function(fun=eq)
You mean like this?
> eq = function(x){x*x}
> plot(eq(1:1000), type='l')
(Or whatever range of values is relevant to your function)
plot has a plot.function method
plot(eq, 1, 1000)
Or
curve(eq, 1, 1000)
Here is a lattice version:
library(lattice)
eq<-function(x) {x*x}
X<-1:1000
xyplot(eq(X)~X,type="l")
Lattice solution with additional settings which I needed:
library(lattice)
distribution<-function(x) {2^(-x*2)}
X<-seq(0,10,0.00001)
xyplot(distribution(X)~X,type="l", col = rgb(red = 255, green = 90, blue = 0, maxColorValue = 255), cex.lab = 3.5, cex.axis = 3.5, lwd=2 )
If you need your range of values for x plotted in increments different from 1, e.g. 0.00001 you can use:
X<-seq(0,10,0.00001)
You can change the colour of your line by defining a rgb value:
col = rgb(red = 255, green = 90, blue = 0, maxColorValue = 255)
You can change the width of the plotted line by setting:
lwd = 2
You can change the size of the labels by scaling them:
cex.lab = 3.5, cex.axis = 3.5
As sjdh also mentioned, ggplot2 comes to the rescue. A more intuitive way without making a dummy data set is to use xlim:
library(ggplot2)
eq <- function(x){sin(x)}
base <- ggplot() + xlim(0, 30)
base + geom_function(fun=eq)
Additionally, for a smoother graph we can set the number of points over which the graph is interpolated using n:
base + geom_function(fun=eq, n=10000)
Function containing parameters
I had a function (emax()) involving 3 parameters (a, b & h) whose line I wanted to plot:
emax = function(x, a, b, h){
(a * x^h)/(b + x^h)
}
curve(emax, from = 1, to = 40, n=40 a = 1, b = 2, h = 3)
which errored with Error in emax(x) : argument "a" is missing, with no default error.
This is fixed by putting the named arguments within the function using this syntax:
curve(emax(x, a = 1, b = 2, h = 3), from = 1, to = 40, n = 40)
which is contrary to the documentation which writes curve(expr, from, to, n, ...) rather than curve(expr(x,...), from, to, n).

Vertical Histogram

I'd like to do a vertical histogram. Ideally I should be able to put multiple on a single plot per day.
If this could be combined with quantmod experimental chart_Series or some other library capable of drawing bars for a time series that would be great. Please see the attached screenshot. Ideally I could plot something like this.
Is there anything built in or existing libraries that can help with this?
I wrote something a year or so ago to do vertical histograms in base graphics. Here it is, with a usage example.
VerticalHist <- function(x, xscale = NULL, xwidth, hist,
fillCol = "gray80", lineCol = "gray40") {
## x (required) is the x position to draw the histogram
## xscale (optional) is the "height" of the tallest bar (horizontally),
## it has sensible default behavior
## xwidth (required) is the horizontal spacing between histograms
## hist (required) is an object of type "histogram"
## (or a list / df with $breaks and $density)
## fillCol and lineCol... exactly what you think.
binWidth <- hist$breaks[2] - hist$breaks[1]
if (is.null(xscale)) xscale <- xwidth * 0.90 / max(hist$density)
n <- length(hist$density)
x.l <- rep(x, n)
x.r <- x.l + hist$density * xscale
y.b <- hist$breaks[1:n]
y.t <- hist$breaks[2:(n + 1)]
rect(xleft = x.l, ybottom = y.b, xright = x.r, ytop = y.t,
col = fillCol, border = lineCol)
}
## Usage example
require(plyr) ## Just needed for the round_any() in this example
n <- 1000
numberOfHists <- 4
data <- data.frame(ReleaseDOY = rnorm(n, 110, 20),
bin = as.factor(rep(c(1, 2, 3, 4), n / 4)))
binWidth <- 1
binStarts <- c(1, 2, 3, 4)
binMids <- binStarts + binWidth / 2
axisCol <- "gray80"
## Data handling
DOYrange <- range(data$ReleaseDOY)
DOYrange <- c(round_any(DOYrange[1], 15, floor),
round_any(DOYrange[2], 15, ceiling))
## Get the histogram obects
histList <- with(data, tapply(ReleaseDOY, bin, hist, plot = FALSE,
breaks = seq(DOYrange[1], DOYrange[2], by = 5)))
DOYmean <- with(data, tapply(ReleaseDOY, bin, mean))
## Plotting
par(mar = c(5, 5, 1, 1) + .1)
plot(c(0, 5), DOYrange, type = "n",
ann = FALSE, axes = FALSE, xaxs = "i", yaxs = "i")
axis(1, cex.axis = 1.2, col = axisCol)
mtext(side = 1, outer = F, line = 3, "Length at tagging (mm)",
cex = 1.2)
axis(2, cex.axis = 1.2, las = 1, line = -.7, col = "white",
at = c(75, 107, 138, 169),
labels = c("March", "April", "May", "June"), tck = 0)
mtext(side = 2, outer = F, line = 3.5, "Date tagged", cex = 1.2)
box(bty = "L", col = axisCol)
## Gridlines
abline(h = c(60, 92, 123, 154, 184), col = "gray80")
biggestDensity <- max(unlist(lapply(histList, function(h){max(h[[4]])})))
xscale <- binWidth * .9 / biggestDensity
## Plot the histograms
for (lengthBin in 1:numberOfHists) {
VerticalHist(binStarts[lengthBin], xscale = xscale,
xwidth = binWidth, histList[[lengthBin]])
}
Violin plots might be close enough to what you want. They are density plots that have been mirrored through one axis, like a hybrid of a boxplot and a density plot. (Much easier to understanding by example than description. :-) )
Here is a simple (somewhat ugly) example of the ggplot2 implementation of them:
library(ggplot2)
library(lubridate)
data(economics) #sample dataset
# calculate year to group by using lubridate's year function
economics$year<-year(economics$date)
# get a subset
subset<-economics[economics$year>2003&economics$year<2007,]
ggplot(subset,aes(x=date,y=unemploy))+
geom_line()+geom_violin(aes(group=year),alpha=0.5)
A prettier example would be:
ggplot(subset,aes(x=date,y=unemploy))+
geom_violin(aes(group=year,colour=year,fill=year),alpha=0.5,
kernel="rectangular")+ # passes to stat_density, makes violin rectangular
geom_line(size=1.5)+ # make the line (wider than normal)
xlab("Year")+ # label one axis
ylab("Unemployment")+ # label the other
theme_bw()+ # make white background on plot
theme(legend.position = "none") # suppress legend
To include ranges instead of or in addition to the line, you would use geom_linerange or geom_pointrange.
If you use grid graphics then you can create rotated viewports whereever you want them and plot to the rotated viewport. You just need a function that will plot using grid graphics into a specified viewport, I would suggest ggplot2 or possibly lattice for this.
In base graphics you could write your own function to plot the rotated histogram (modify the plot.histogram function or just write your own from scratch using rect or other tools). Then you can use the subplot function from the TeachingDemos package to place the plot wherever you want on a larger plot.

Resources