1

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)
PhysWhiz
  • 13
  • 6
  • 1
    Providing an answer would be so much easier and more fun with a [minimal reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – RHertel Jul 18 '15 at 18:53
  • My bad, it's my first time on stack overflow, will be back with a "minimal reproducible example" asap. – PhysWhiz Jul 18 '15 at 18:57
  • 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 Jul 18 '15 at 21:32
  • 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 Jul 18 '15 at 22:16
  • 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 Jul 19 '15 at 12:21
  • I got scale_size_continuous to function by specifying the point size in ggplot as opposed to geom_point as so `samplePlot <- ggplot(sampleDataFrame, aes(x = xSample, y = ySample, size = pointSize))`, thing is, if I stretch the graph the points aren't being stretched with the axes, it is just rescaling the points independently of the axes. – PhysWhiz Jul 19 '15 at 14:19

2 Answers2

1

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

baptiste
  • 75,767
  • 19
  • 198
  • 294
1

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)
baptiste
  • 75,767
  • 19
  • 198
  • 294