labeling lines value in countour plot using ggplot2 in R [duplicate] - r

I wonder how to get data labels on lines in ggplot2 for contours. Thanks
require(grDevices) # for colours
x <- seq(-4*pi, 4*pi, len = 27)
y <- seq(-4*pi, 4*pi, len = 27)
r <- sqrt(outer(x^2, y^2, "+"))
rx <- range(x <- 10*1:nrow(volcano))
ry <- range(y <- 10*1:ncol(volcano))
ry <- ry + c(-1, 1) * (diff(rx) - diff(ry))/2
plot(
x = 0
, y = 0
, type = "n"
, xlim = rx
, ylim = ry
, xlab = ""
, ylab = ""
)
contour(
x = x
, y = y
, z = volcano
, add = TRUE
)
library(ggplot2)
library(reshape2)
volcano3d <- melt(volcano)
names(volcano3d) <- c("x", "y", "z")
# Basic plot
v <- ggplot(volcano3d, aes(x, y, z = z))
v + stat_contour()

using directlabels package and picking solution from this
# Basic plot
v <- ggplot(volcano3d, aes(x, y, z = z))
library(directlabels)
v2 <- v + stat_contour(aes(colour = ..level..))
direct.label(v2, method="bottom.pieces")

This is an old question already answered, but I do a lot of contour plots and I think that there is an easier and more versatile way to do this using the package metR (https://rdrr.io/github/eliocamp/metR/f/vignettes/Visualization-tools.Rmd). This package has the function geom_label_contour() that provides an easy way to plot labels of contours. Also provides a lot of functions to plot maps.
library(ggplot2)
library(reshape2)
library(metR)
volcano3d <- melt(volcano)
colnames(volcano3d) <- c('x','y','z')
ggplot(data = volcano3d, aes(x=x,y=y,z=z)) + geom_contour() +
geom_label_contour()

Related

List of plots generated in ggplot2 using scale_color_gradientn have wrong coloring

I'm attempting to use library(scales) and scale_color_gradientn() to create a custom mapping of colors to a continuous variable, in an attempt to limit the effect of outliers on the coloring of my plot. This works for a single plot, but does not work when I use a loop to generate several plots and store them in a list.
Here is a minimal working example:
library(ggplot2)
library(scales)
data1 <- as.data.frame(cbind(x = rnorm(100),
y = rnorm(100),
v1 = rnorm(100, mean = 2, sd = 1),
v2 = rnorm(100, mean = -2, sd = 1)))
#add outliers
data1[1,"v1"] <- 200
data1[2,"v1"] <- -200
data1[1,"v2"] <- 50
data1[2,"v2"] <- -50
#define color palette
cols <- colorRampPalette(c("#3540FF","black","#FF3535"))(n = 100)
#simple color scale
col2 <- scale_color_gradient2(low = "#3540FF",
mid = "black",
high = "#FF3535"
)
#outlier-adjusted color scale
{
aa <- min(data1$v1)
bb <- quantile(data1$v1, 0.05)
cc <- quantile(data1$v1, 0.95)
dd <- max(data1$v1)
coln <- scale_color_gradientn(colors = cols[c(1,5,95,100)],
values = rescale(c(aa,bb,cc,dd),
limits = c(aa,dd))
)
}
Plots:
1. Plot with simple scales - outliers cause scales to stretch out.
ggplot(data1, aes(x = x, y = y, color = v1))+
geom_point()+
col2
2. Plot with outlier-adjusted scales - correct color scaling.
ggplot(data1, aes(x = x, y = y, color = v1))+
geom_point()+
coln
3. The scales for v1 do not work for v2 as the data is different.
ggplot(data1, aes(x = x, y = y, color = v2))+
geom_point()+
coln
#loop to produce list of plots each with own scale
{
plots <- list()
k <- 1
for (i in c("v1","v2")){
aa <- min(data1[,i])
bb <- quantile(data1[,i],0.05)
cc <- quantile(data1[,i], 0.95)
dd <- max(data1[,i])
colm <- scale_color_gradientn(colors = cols[c(1,5,95,100)],
values = rescale(c(aa,bb,cc,dd),
limits = c(aa,dd)))
plots[[k]] <- ggplot(data1, aes_string(x = "x",
y = "y",
color = i
))+
geom_point()+
colm
k <- k + 1
}
}
4. First plot has the wrong scales.
plots[[1]]
5. Second plot has the correct scales.
plots[[2]]
So I'm guessing this has something to do with the scale_color_gradientn() function being called when the plotting takes place, rather than within the loop.
If anyone can help with this, it'd be much appreciated. In base R I would bin the continuous data and assigning hex colors into a vector used for fill color, but I'm unsure how I can apply this within ggplot.
You need to use a closure (function with associated environment):
{
plots <- list()
k <- 1
for (i in c("v1", "v2")){
colm <- function() {
aa <- min(data1[, i])
bb <- quantile(data1[, i], 0.05)
cc <- quantile(data1[, i], 0.95)
dd <- max(data1[, i])
scale_color_gradientn(colors = cols[c(1, 5, 95, 100)],
values = rescale(c(aa, bb, cc, dd),
limits = c(aa, dd)))
}
plots[[k]] <- ggplot(data1, aes_string(x = "x",
y = "y",
color = i)) +
geom_point() +
colm()
k <- k + 1
}
}
plots[[1]]
plots[[2]]

Cumulative Density Plots with ggplot and plotly

When we take the following example from ggplot2 docs
df <- data.frame(x = c(rnorm(100, 0, 3), rnorm(100, 0, 10)),
g = gl(2, 100))
library(ggplot2)
p <- ggplot(df, aes(x, colour = g)) +
stat_ecdf(geom = "step", na.rm = T) + # interchange point and step
theme_bw()
p
We can create a standard cdf plot. Now if we want to play with the plot in plotly, I obtain a very confusing image when I use the step command. See below. However, when I use the point command plotly behaves like it should. What is happening with the step command? Why can't I recreate the image from using ggplot only?
library(plotly)
ggplotly(p)
I found the solution here https://community.plotly.com/t/bug-with-ggplot2-stat-ecdf-function/1187/3.
You should reorder the dataframe along x.
df <- dplyr::arrange(df, x)
library(ggplot2)
p <- ggplot(df, aes(x, colour = g)) +
stat_ecdf(geom = "step", na.rm = T) +
theme_bw()
p
library(plotly)
ggplotly(p)
This can be solved using ecdf() function.
## ecdf function to get y and 1-y
rcdf <- function (x) {
cdf <- ecdf(x)
y1 <- cdf(x)
y <- unique(y1)
# xrcdf <- 1-y ## to get reverse cdf
xrcdf <- y ## to get cdf
}
ug <- unique(df$g)
ng <- length(ug)
xll <- min(df$x)
xul <- max(df$x)
adr <- data.frame(myxx=c(), myyy=c(), mygg=c())
lapply(1:ng, function(i){
ad2r <- subset(df, g==ug[i])
myx1 <- unique(ad2r$x)
myxx <- c(xll,myx1,xul) ## add lowest value - dummy to assign 100%
myy1 <- rcdf(ad2r$x)
# myyy <- c(1.0,myy1,0.0) ## add 100% to get reverse cdf
myyy <- c(0.0,myy1,1.0) ## add 0% to get cdf
mygg <- ug[i]
ad2rf <- data.frame(myxx,myyy,mygg)
adr <<- rbind(adr,ad2rf)
})
adf <- adr[order(adr$myxx),]
pp <- ggplot(data=adf,
aes_(x=adf$myxx, y=100*adf$myyy, col=adf$mygg, group=adf$mygg)) +
geom_step() +
labs(title="CDF", y = "Y", x = "X", col=NULL)
ppp <- ggplotly(pp, tooltip=c("x","y"))
ppp
This gives the following output:
CDF

3D Data with ggplot

I have data in the following form:
x <- seq(from = 0.01,to = 1, by = 0.01)
y <- seq(from = 0.01,to = 1, by = 0.01)
xAxis <- x/(1+x*y)
yAxis <- x/(1+x*y)
z <- (0.9-xAxis)^2 + (0.5-yAxis)^2
df <- expand.grid(x,y)
xAxis <- df$Var1/(1+df$Var1*df$Var2)
yAxis <- df$Var2/(1+df$Var1*df$Var2)
df$x <- xAxis
df$y <- yAxis
df$z <- z
I would like to plot te (x,y,z) data as a surface and contour plots, possibily interpolating data to obtain as smooth a figure as possible.
Searching I reached the akima package which does the interpolation:
im <- with(df,interp(x,y,z))
I am having trouble plotting the data with this output. Ideally I would like to use ggplot2 since I want to add stuff to the original plot.
Thanks!
I'm a bit puzzled as to what you are looking for, but how about something like this?
im <- with(df, akima::interp(x, y, z, nx = 1000, ny = 1000))
df2 <- data.frame(expand.grid(x = im$x, y = im$y), z = c(im$z))
ggplot(df2, aes(x, y, fill = z)) +
geom_raster() +
viridis::scale_fill_viridis()
For contour plots, I use the "rgl" package. This allows real-time manipulation of the plot in order to have the best view.
library("rgl")
x <- seq(from = 0.01,to = 1, by = 0.01)
y <- seq(from = 0.01,to = 1, by = 0.01)
#z <- (0.9-xAxis)^2 + (0.5-yAxis)^2
df <- expand.grid(x,y)
xAxis <- df$Var1/(1+df$Var1*df$Var2)
yAxis <- df$Var2/(1+df$Var1*df$Var2)
df$z <- (0.9-xAxis)^2 + (0.5-yAxis)^2
surface3d(x=x, y=y, z=df$z, col="blue", back="lines")
title3d(xlab="x", zlab="z", ylab="y")
axes3d(tick="FALSE")
The rgl package is comparable to the ggplot2 package to customize the final plot. The 0.01 grid spacing is more than close enough for this type of smooth surface.

Add new points into a contour plot in ggplot2

I am trying to plot some extra points onto an existing contour plot with ggplot2:
require(ggplot2)
library(reshape2) # for melt
volcano3d <- melt(volcano)
names(volcano3d) <- c("x", "y", "z")
v <- ggplot(volcano3d, aes(x, y, z = z))
v <- v + stat_contour()
print(v)
newdata <- data.frame(x = runif(7)*60, y = runif(7)*60)
v <- v + geom_point(data=newdata, aes(x, y))
print(v)
The first print is ok, but the second is just blank. Why?

Custom levels in ggplot2 contour plot?

Here is a code snippet from the docs site:
# Generate data
library(reshape2) # for melt
volcano3d <- melt(volcano)
names(volcano3d) <- c("x", "y", "z")
# Basic plot
v <- ggplot(volcano3d, aes(x, y, z = z))
v + stat_contour(binwidth = 10)
Output:
What if I want to draw contour lines at custom levels? For example, in the volcano3d data set, I want these levels to be indicate: z == 120, 140, 160.
Replace binwidth= with argument breaks= and provide breakpoint you need.
ggplot(volcano3d, aes(x, y, z = z)) +
stat_contour(breaks=c(120,140,160))

Resources