Captain Hat
Captain Hat

Reputation: 3237

Why is the SVG of my raster plot so blurry?

I'm trying to print a raster visualisation. It renders fine in RStudio, but when I save it using the base svg device it comes out super blurry - as though each square of the raster is a massive pixel and they've been interpolated at some stage in the process.

Here's a reprex:

## libraries / set up
require(dplyr)
require(ggplot2)

set.seed(11)

## Generate data
### Make 100 random(ish) pairings of eye and hair colour to visualise
possibleEye <- c("green", "green", "green", 
                          "blue", "blue", "brown", "hazel")
possibleHair <- c("blonde", "blonde", "brown",
                  "gray", "gray", "gray", "ginger")
eyeColours <- sample(possibleEye, 100, replace = TRUE)
hairColours <- sample(possibleHair, 100, replace = TRUE)

plotData <- tibble(
  eye.colour = factor(eyeColours),
  hair.colour = factor(hairColours)
)

### Count the occurrences of each combination
plotData <- 
  plotData |> 
  group_by(hair.colour, eye.colour) |> 
  count()

## Plot raster

rasterPlot <- 
  ggplot(plotData, aes(x = eye.colour, y = hair.colour, fill = n)) +
  geom_raster()

rasterPlot

## save SVG file

svg("my-raster.svg")
print(rasterPlot)
dev.off()
#> png 
#>   2

Created on 2022-02-07 by the reprex package (v2.0.1)

But this is what my SVG looks like:

svg print of raster image, in which the squares are blurry

Why is that happening? How can I stop it from happening?

It's not a fault with the software I'm using to view the SVG, because it looks the same when viewed in either Inkscape or Google Chrome.

Here's my R.Version():

$platform
[1] "x86_64-w64-mingw32"

...

$version.string
[1] "R version 4.1.1 (2021-08-10)"

$nickname
[1] "Kick Things"

Upvotes: 1

Views: 402

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173803

The geom_raster is being interpreted as a low-res raster, so it seems that the svg device is attempting to interpolate it (you will see the same image in the plotting window if you use geom_raster(interpolate = TRUE)). One way round this is to use geom_tile instead:

rasterPlot <- 
  ggplot(plotData, aes(x = eye.colour, y = hair.colour, fill = n)) +
  geom_tile(colour = NA, height = 1.01, width = 1.01)

svg("my-raster.svg")
print(rasterPlot)
dev.off()

enter image description here

Alternatively, you can keep the geom_raster and use ggsave (you need to have the svglite package installed for this)

rasterPlot <- 
  ggplot(plotData, aes(x = eye.colour, y = hair.colour, fill = n)) +
  geom_raster()

ggsave("my_svg.svg", rasterPlot, device = "svg")

enter image description here

Upvotes: 1

Related Questions