1
votes

I have written the following code to plot my x-y data on a set of re-scaleable axes, the values contained in pointSize are the correctly scaled vertical/horizontal diameters of the point I want at each plotted coordinate. How do I go about getting this to work? Right now I am just plotting points with whatever scaling is used by default in geom_point(aes(size)) and the points don't scale with the axes. Once I rescale the axes with coord_cartesian I want the plotted points to increase/decrease relative to the axes accordingly.

For example, if the point size is say 5, that means I want the horizontal and vertical diameter of the point to be 5 relative to the axes regardless of specified xyScaling.

EDIT: min in pointSize should have been min = 0, not min = -10

Minimal reproducible code:

# Sample size & x-y axes plot boundaries
sampleSize <- 100

# Set scale factor of x-y axes
xyScaling <- 1

# Set to false once sampled to rescale axis with same distributions
resample <- TRUE

if (resample == TRUE){
  xSample <- replicate(sampleSize, runif(1, min = -sampleSize/2, max = sampleSize/2))

  ySample <- replicate(sampleSize, runif(1, min = -sampleSize/2, max = sampleSize/2))

  pointSize <- replicate(sampleSize, runif(1, min = 0, max = 10))
}

sampleDataFrame <- data.frame(xSample, ySample, pointSize)
samplePlot <- ggplot(sampleDataFrame, aes(xSample, ySample))
samplePlot +
geom_point(data = sampleDataFrame, aes(size = sampleDataFrame$pointSize[])) + 
coord_cartesian(xlim = c((xyScaling*(-sampleSize/2)),(xyScaling*(sampleSize/2))),
                ylim = c((xyScaling*(-sampleSize/2)),(xyScaling*(sampleSize/2)))) +
xlab("x") +
ylab("y") +
scale_size_identity(guide=FALSE)

EDIT: So I almost managed to solve the problem by using geom_rect, the following code does what I want with the caveat that the points are rectangles as opposed to ellipses/circles, I couldn't get this to work with ellipses, if anyone could guide me to the right function I would be very grateful.

sampleDataFrame <- data.frame(xSample, ySample, pointSize)

samplePlot <- ggplot(sampleDataFrame)
samplePlot +
  geom_point(aes(xSample, ySample, size = 0)) + 
  geom_rect(aes(xmin = xSample-(pointSize/2), xmax = xSample+(pointSize/2), ymin = ySample-(pointSize/2), ymax = ySample+(pointSize/2))) +
  coord_cartesian(xlim = c((xyScaling*(-sampleSize/2)),(xyScaling*(sampleSize/2))),
                  ylim = c((xyScaling*(-sampleSize/2)),(xyScaling*(sampleSize/2)))) +
  xlab("x") +
  ylab("y") +
  scale_size_identity(guide=FALSE)
2
Providing an answer would be so much easier and more fun with a minimal reproducible example. - RHertel
My bad, it's my first time on stack overflow, will be back with a "minimal reproducible example" asap. - PhysWhiz
As a hint wrt having the same sample data in running the script off again, if you use the command set.seed(1000) where 1000 can ofc be any number, the same random numbers will be chosen. It's somewhat like R has a list of 'random' numbers stored, and the set.seed function tells it at what point to start reading off the list. - Akhil Nair
Try giving the function + scale_size_continuous(range = c(0, max)) a play. With regards to the max point, you'll have to tune that geometrically to match your scaling, but this is the argument that will actually grow and shrink the points as you're expecting. Also, changing your geom_point call to + geom_point(aes(size = pointSize)) will be sufficient, rather than what you have (as you're not overriding the data, and the aesthetics can see sampleDataFrame's column names). - Akhil Nair
Hmmm, I've tried adding scale_size_continuous after geom_point so that it reads geom_point(data = sampleDataFrame, aes(size = pointSize)) + scale_size_continuous(range = c(0, 30)) + ... and I have altered max arbitrarily but it doesn't seem to be having any affect . - PhysWhiz

2 Answers

1
votes

this has been suggested in the past, but I don't think it got implemented. One problem is that circles are only circular in the special case of cartesian coordinates with unit aspect ratio. The easiest workaround is probably to create a data.frame with xy positions describing circles (ellipses) and draw these as polygons.

library(gridExtra)
library(ggplot2)

circle <- polygon_regular(50)

pointy_points <- function(x, y, size){
  do.call(rbind, mapply(function(x,y,size,id) 
    data.frame(x=size*circle[,1]+x, y=size*circle[,2]+y, id=id),
         x=x,y=y, size=size, id=seq_along(x), SIMPLIFY=FALSE))

}

test <- pointy_points(1:10, 1:10, size=seq(0.2, 1, length.out=10))

ggplot(test, aes(x,y,group=id, fill=id)) + geom_polygon()

enter image description here

1
votes

You could try to edit the points at the lowest-level, but it's quite fiddly,

library(ggplot2); library(grid)
p <- qplot(1:10, 1:10, size=I(10))
g <- ggplotGrob(p)

points <- g$grobs[[4]][["children"]][[2]]
g$grobs[[4]][["children"]][[2]] <- 
  editGrob(points, size = convertUnit(points$size, unitTo = "npc"))

grid.newpage()
grid.draw(g)