How to use sec_axis() for discrete data in ggplot2 R?
Asked Answered
C

1

9

I have discreet data that looks like this:

height <- c(1,2,3,4,5,6,7,8)
weight <- c(100,200,300,400,500,600,700,800)
person <- c("Jack","Jim","Jill","Tess","Jack","Jim","Jill","Tess")
set <- c(1,1,1,1,2,2,2,2)
dat <- data.frame(set,person,height,weight)

I'm trying to plot a graph with same x-axis(person), and 2 different y-axis (weight and height). All the examples, I find is trying to plot the secondary axis (sec_axis), or discreet data using base plots. Is there an easy way to use sec_axis for discreet data on ggplot2? Edit: Someone in the comments suggested I try the suggested reply. However, I run into this error now

Here is my current code:

p1 <- ggplot(data = dat, aes(x = person, y = weight)) + 
  geom_point(color = "red") + facet_wrap(~set, scales="free") 
p2 <- p1 + scale_y_continuous("height",sec_axis(~.*1.2, name="height"))
p2

I get the error: Error in x < range[1] : 
  comparison (3) is possible only for atomic and list types

Alternately, now I have modified the example to match this example posted.

p <- ggplot(dat, aes(x = person))
p <- p + geom_line(aes(y = height, colour = "Height"))

# adding the relative weight data, transformed to match roughly the range of the height
p <- p + geom_line(aes(y = weight/100, colour = "Weight"))

# now adding the secondary axis, following the example in the help file ?scale_y_continuous
# and, very important, reverting the above transformation
p <- p + scale_y_continuous(sec.axis = sec_axis(~.*100, name = "Relative weight [%]"))

# modifying colours and theme options
p <- p + scale_colour_manual(values = c("blue", "red"))
p <- p + labs(y = "Height [inches]",
              x = "Person",
              colour = "Parameter")
p <- p + theme(legend.position = c(0.8, 0.9))+ facet_wrap(~set, scales="free") 
p

I get an error that says

"geom_path: Each group consists of only one observation. Do you need to 
 adjust the group aesthetic?"

I get the template, but no points get plotted

Clearcole answered 4/9, 2017 at 23:55 Comment(6)
Those are continuous data (numbers), not discrete (categories).Solutrean
I realized I linked the incorrect source. I have linked the correct one and updated my answer with the error, if I use itClearcole
Add sec.axis = in front of your sec_axis(...). Without naming the argument explicitly, it defaulted to the 2nd argument in scale_y_continuous(), & breaks = sec_axis(~.*1.2, name="height") triggers that error because it made no sense in context.Psalter
Like this p1 + scale_y_continuous("height", sec_axis(sec.axis= ~.*1.2, name="height")) ? This throws me an errorClearcole
As far as I know ggplot2 does not support independent secondary axis. All secondary axes must be based on a one-to-one transformation of the primary axes.Centigrade
I think that was the case some years ago, but now they seem to have sec_axis, that seems to do the job for others. Not able to get it work for me.Clearcole
H
0

R function arguments are fed in by position if argument names are not specified explicitly. As mentioned by @Z.Lin in the comments, you need sec.axis= before your sec_axis function to indicate that you are feeding this function into the sec.axis argument of scale_y_continuous. If you don't do that, it will be fed into the second argument of scale_y_continuous, which by default, is breaks=. The error message is thus related to you not feeding in an acceptable data type for the breaks argument:

p1 <- ggplot(data = dat, aes(x = person, y = weight)) + 
  geom_point(color = "red") + facet_wrap(~set, scales="free") 
p2 <- p1 + scale_y_continuous("weight", sec.axis = sec_axis(~.*1.2, name="height"))
p2

![enter image description here

The first argument (name=) of scale_y_continuous is for the first y scale, where as the sec.axis= argument is for the second y scale. I changed your first y scale name to correct that.

Highlander answered 5/9, 2017 at 3:27 Comment(4)
But this does not seem to plot the weight and height. I need both the weight and height to be plotted on the same x-axis.Clearcole
@Ash It's just the label that's not specified correctly. See my edited answer.Highlander
No. I don't think you see my point. For each person, eg. In Set1, for Jack I should be seeing two points, one that corresponds to his height (say marked in red) and the other to his weight (say marked in black). The plot here instead is yielding a single points, perhaps a relationship between weight and height? That is not what I want.Clearcole
@Ash I see, you actually want two different y axes on the same plot. In this case, sec.axis is not the right solution, since it only allows for a second axis that is a linear transformation of the first axis. I think there are no good solutions with ggplot2 because it is by design to discourage misrepresentation of data. See this discussion: #3099719Highlander

© 2022 - 2024 — McMap. All rights reserved.