Getting "npc" coordinates of ggplot2 grob - r

The grid package used for generating graphics in the R language uses so-called "normal parent coordinates" (npc) to position graphical objects ("grobs").
Is it possible to get the npc coordinates of a ggplot2 grob?
This would be of major help for drawing lines (for connecting data points) across facets (ggplot, drawing line between points across facets contains a solution, but this is very hard to follow for beginners)
library(ggplot2)
library(grid)
# Generate some sample data
df <- data.frame(y=c(1,2,3),x=1,Set=LETTERS[1:3])
# Plot
ggplot(df,aes(x,y)) +
geom_point(aes(fill=Set),color="black",shape=21,size=3) +
facet_grid(~Set)
# It is easy to list the grobs, but I can't see their npc coordinates
grid.ls(grid.force())

Related

How to plot colored circles knowing X/Y coordinates, radius and a continuous 3rd parameter in R

In a telecommunication project I have a data basis of a list of antennas with their XY coordinates, emission radius and frequencies. I would like to represent with circles the covered area of each antennas, with a specific color depending on the frequency.
Ive been looking for libraries, but I'm very new to R and programmation in general, and I don't find any easy and simple ones. What would you recommend ?
Thank you for any help
You can do it with ggplot2 and ggforce package, like this:
# First generate a sample data
data <- data.frame(x=rnorm(50),y=rnorm(50),radius = rnorm(50,sd=0.1),freq = factor(1:5,levels=1:5))
# Load the package
library(ggplot2)
library(ggforce)
# Plot
ggplot(data=data,aes(x0=x,y0=y,col=freq,r=radius)) + geom_circle() +
coord_fixed()

Adding a polar background to a ggplot without using polar coordinates

I'd like make a plot using cartesian coordinate system, but then have it overlaid on a polar plot background, like that produced by coord_polar. Panel.background from theme.R only has element_rect; Ideally I could use something like element_polar.
Any way to do this?
Simply using coord_polar doesn't work because I'm also plotting various other geoms that map idiosyncratically onto coord_polar (geom_ellispis from the ggforce package, for example).
Reproducible example code:
library(ggplot2)
library(ggforce) # NB this is the github version #install_github("thomasp85/ggforce"). Includes 'geom_ellipsis'
#### Make example data
r<-runif(50,-100,100) # radial coordinates
theta<-runif(50,0,2) # theta
a<-runif(50,1,20)
b<-runif(50,1,20)
# Convert r and theta to cartesian:
x<-r*cos(theta*pi) # x-coordinate of ellipse foci
y<-r*sin(theta*pi) # y-coordinate of ellipse foci
angle.random<-runif(50,min=0,max=2) # random angle for ellipsis rotation
df<-as.data.frame(cbind(r,theta,x,y,a,b,angle.random))
# Make plots
# Plot should look like this:
ggplot(df,aes(x,y))+
geom_point(aes(x,y))+
geom_ellipsis(data=df,aes(x0=x,y0=y,a=a,b=b,angle=angle.random,fill=T))
# But I want the panel background in polar coordinates (and auto-adjusing to scale), like this:
ggplot(df,aes(x,y))+
geom_point(aes(x,y))+
coord_polar()
# However, using geom_ellipsis (among other functions) has idiosyncratic effects in non-cartesian coordinate systems:
ggplot(df,aes(r,theta))+
geom_point(aes(x,y))+
geom_ellipsis(data=df,aes(x0=x,y0=y,a=a,b=b,angle=angle.random,fill=T))+
coord_polar()
I would like the polar background from the 3rd plot, with the un-distorted ellipses from the first plot. Is there any way to do this?

R, Plotting points with Labels on a single (horizontal) numberline

For educational purpose I'm trying to plot a singel horizontal "numberline" with some datapoints with labels in R. I came this far;
library(plotrix)
source("spread.labels.R")
plot(0:100,axes=FALSE,type="n",xlab="",ylab="")
axis(1,pos=0)
spread.labels(c(5,5,50,60,70,90),rep(0,6),ony=FALSE,
labels=c("5","5","50","60","70","90"),
offsets=rep(20,6))
This gave me a numberline with smaller lines pointing up to (and a little bit "in") the labels from where the datapoints should lie on the numberline - but without the points itself. Can anyone give me additional or alternative R-codes for solving thess problems:
- datapoints itself still missing are not plotted,
- and labels maybe not evenly divided over the whole numberline,
- and lines come into the labels and not merely point to the labels
Thank a lot,
Benjamin Telkamp
I usually like to create plots using primitive base R graphics functions, such as points(), segments(), lines(), abline(), rect(), polygon(), text(), and mtext(). You can easily create curves (e.g. for circles) and more complex shapes using segments() and lines() across granular coordinate vectors that you define yourself. For example, see Plot angle between vectors. This provides much more control over the plot elements you create, however, it often takes more work and careful coding than more "pre-packaged" solutions, so it's a tradeoff.
For your case, it sounds to me like you're happy with what spread.labels() is trying to do, you just want the following changes:
add point symbols at the labelled points.
prevent overlap between labels and lines.
Here's how this can be done:
## define plot data
xlim <- c(0,100);
ylim <- c(0,100);
px <- c(5,5,50,60,70,90);
py <- c(0,0,0,0,0,0);
lx.buf <- 5;
lx <- seq(xlim[1]+lx.buf,xlim[2]-lx.buf,len=length(px));
ly <- 20;
## create basic plot outline
par(xaxs='i',yaxs='i',mar=c(5,1,1,1));
plot(NA,xlim=xlim,ylim=ylim,axes=F,ann=F);
axis(1);
## plot elements
segments(px,py,lx,ly);
points(px,py,pch=16,xpd=NA);
text(lx,ly,px,pos=3);

How to make a ggplot2 contour plot analogue to lattice:filled.contour()?

I've been learning ggplot2, and hope to use it for all my R graphing. However, I've yet to find a way to make a contour plot that looks analogous to a conventional contour plot, like what can be obtained using lattice:filled.contour(). For example:
#define data
x<-seq(1,11,1)
y<-seq(1,11,1)
xyz.func<-function(x,y) {-10.4+6.53*x+6.53*y-0.167*x^2-0.167*y^2+0.0500*x*y}
#contour plot using lattice graphics and R Color Brewer
library(lattice) #for filled.contour()
library(RColorBrewer) #for brewer.pal()
z.lattice<-outer(x,y,xyz.func)
filled.contour(x,y,z.lattice,nlevels=6,col=brewer.pal(6,"YlOrRd"))
This gives me a nice contour plot.
Now, let's try the same thing in ggplot2. The best I can come up with, based on everything I've read (particularly Drawing labels on flat section of contour lines in ggplot2) is:
#contour plot using ggplot2
library(ggplot2)
library(reshape2) #for melt()
z.molten<-melt(z.lattice)
names(z.molten) <- c("x", "y", "z")
v<-ggplot(z.molten, aes(x,y,z=z))+
geom_tile(aes(fill=z))+
stat_contour(bins=6,aes(x,y,z=z), color="black", size=0.6)+
scale_fill_gradientn(colours=brewer.pal(6,"YlOrRd"))
v
This graph has the same basic idea as filled.contour(), but the colored tiles don't conform to the contours very well.
I haven't been successful with changing the sizes of the tiles, either.
Any suggestions on how to make ggplot2's output closer to filled.contour()'s output?
The essence of your question, it seems, is how to produce a contour plot in ggplot with discrete filled contours, rather than continuous contours as you would get using the conventional geom_tile(...) approach. Here is one way.
x<-seq(1,11,.03) # note finer grid
y<-seq(1,11,.03)
xyz.func<-function(x,y) {-10.4+6.53*x+6.53*y-0.167*x^2-0.167*y^2+0.0500*x*y}
gg <- expand.grid(x=x,y=y)
gg$z <- with(gg,xyz.func(x,y)) # need long format for ggplot
library(ggplot2)
library(RColorBrewer) #for brewer.pal()
brks <- cut(gg$z,breaks=seq(0,100,len=6))
brks <- gsub(","," - ",brks,fixed=TRUE)
gg$brks <- gsub("\\(|\\]","",brks) # reformat guide labels
ggplot(gg,aes(x,y)) +
geom_tile(aes(fill=brks))+
scale_fill_manual("Z",values=brewer.pal(6,"YlOrRd"))+
scale_x_continuous(expand=c(0,0))+
scale_y_continuous(expand=c(0,0))+
coord_fixed()
The use of, e.g., scale_x_continuos(...) is just to get rid of the extra space ggplot puts around the axis limits; fine for most things but distracting in contour plots. The use of coord_fixed(...) is just to set the aspect ratio to 1:1. These are optional.

Splitting ggplot plot map into 3 frames

Is it possible to extract specific sections of a ggplot figure/map and place them side by side in a secondary figure but still add points to the three frames as if they were still one plot i.e. for the following map
create a map split into 3 sections which can then be manipulated as one graph (i.e. adding points to all three sections of the graph simultaneously?
UPDATE: Reproducible example
set.seed(1)
dfx<-c(sample(1:1000,100),sample(2000:3000,100),sample(4000:3000,100))
dfy<-c(sample(1:1000,100),sample(2000:3000,100),sample(4000:3000,100))
p<-ggplot()+
coord_fixed()+
geom_point(aes(x=dfx,y=dfy))
p
I can get partway there but can't retain the effects of coord_equal or coord_fixed while allowing free scales ... hopefully someone else can step in and get the rest of the way. (This has come up before -- scatterplot with equal axes -- but I haven't seen a solution.)
dd <- data.frame(dfx,dfy)
dd2 <- transform(dd,panel=cut(dfx,seq(0,4000,by=1000),labels=1:4))
p <- ggplot(dd2)+geom_point(aes(dfx,dfy)) + coord_equal()
p + facet_wrap(~panel,nrow=1,scale="free")

Resources