Auto scale data in R

10,299

Solution 1

I agree with Richie Cotton that having two axes is considered bad form.

However, there is an alternative way of displaying the information that is conceptually sound. This is to scale the values between 0 and 1.

Here is an example using ggplot.

library(reshape2)
library(ggplot2)

gales <- structure(list(
  year = 1950:1970,
  number = c(600L, 1200L, 900L, 800L, 800L, 1100L, 600L, 900L, 1200L, 1200L, 800L, 900L, 800L, 1200L, 900L, 600L, 600L, 600L, 600L, 600L, 1200L),
  feb = c(20L, 5L, 5L, 5L, 5L, 20L, 6L, 10L, 20L, 20L, 6L, 6L, 10L, 20L, 15L, 10L, 10L, 10L, 10L, 10L, 20L)),
  .Names = c("year", "number", "feb"), class = "data.frame", row.names = c(NA, -21L)
)

Define a function that will scale values between [0; 1] corresponding to [min; max]

range01 <- function(x){(x-min(x))/(max(x)-min(x))}

gales$number <- range01(gales$number)
gales$feb <- range01(gales$feb)

Melt data to long format suitable for plotting in ggplot

mgales <- melt(gales, id.vars="year")

Create the plot

ggplot(mgales, aes(x=year, y=value, group=variable, colour=variable)) +
  geom_line(size=2)

enter image description here

Solution 2

Having two lines with different scales on the same graph is generally considered bad form. (See, e.g., "Dual-Scaled Axes in Graphs" in the Perceptual Edge library.)

A better solution would be to have two panels, one above the other, with a common time axis. This is most easily done using ggplot2 or lattice.

A ggplot2 solution:

library(ggplot2)
gales_long <- melt(gales, id.vars = "year")

p_gales_ggplot2 <- ggplot(gales_long, aes(year, value)) +
  geom_line() +
  facet_grid(variable ~ ., scales = "free_y")
p_gales_ggplot2

And a lattice solution:

p_gales_lattice <- xyplot(
  value ~ year | variable,
  gales_long,
  type = "l",
  scales = list(y = list(relation = "free")),
  layout = c(1, 2)
)
p_gales_lattice
Share:
10,299

Related videos on Youtube

repinementer
Author by

repinementer

Updated on May 29, 2022

Comments

  • repinementer
    repinementer almost 2 years

    I'm using the following code to draw plots of two different data on same graph. And it is working well. But the problem is I'm manually scaling the data. Is it possible to autoscale them?

    Here is my script

    gales <- read.table("input", header=TRUE)
    attach(gales)
    par(mar=c(5,4,4,4)+0.1)
    plot(year,number,type="l",lwd=2,las=1, col="red")
    title(main = list("Title", cex=1.5,
                      col="red", font=3))
    par(new=T)
    plot(year,feb,type="l",lwd=2, las=1,axes=F,ylab="",col="blue")
    axis(4,las=1)
    mtext(side=4,line=2.5,"feb")
    

    Here is my data

    year    number  feb
    1950    600 20
    1951    1200    5
    1952    900 5
    1953    800 5
    1954    800 5
    1955    1100    20
    1956    600 6
    1957    900 10
    1958    1200    20
    1959    1200    20
    1960    800 6
    1961    900 6
    1962    800 10
    1963    1200    20
    1964    900 15
    1965    600 10
    1966    600 10
    1967    600 10
    1968    600 10
    1969    600 10
    1970    1200    20
    

    gales <- structure(list(
        year = 1950:1970,
        number = c(600L, 1200L, 900L, 800L, 800L, 1100L, 600L, 900L, 1200L, 1200L, 800L, 900L, 800L, 1200L, 900L, 600L, 600L, 600L, 600L, 600L, 1200L),
        feb = c(20L, 5L, 5L, 5L, 5L, 20L, 6L, 10L, 20L, 20L, 6L, 6L, 10L, 20L, 15L, 10L, 10L, 10L, 10L, 10L, 20L)),
        .Names = c("year", "number", "feb"), class = "data.frame", row.names = c(NA, -21L)
    )
    
    • Marek
      Marek about 13 years
      Please use dput to provide data. It will keep all nuances of your data (as data types) and it's easier to read it, so you got answer faster. I edit your question to give you example.