3

I've had a good look around this site and others on how to set the hjust and vjust according to a value in a particular column. The following shows how the data is structured (but is a simplified subset of many entries for many years):

    YearStart <- c(2001,2002,2003,2001,2002,2003)
    Team <- c("MU","MU","MU","MC","MC","MC")
    Attendance <- c(67586,67601,67640,33058,34564,46834)
    Position <- c(3,1,3,1,9,16)
    offset <-c()

    df <- data.frame(YearStart,Team,Attendance,Position)

so

> head(df)
  YearStart Team Attendance Position
1      2001   MU      67586        3
2      2002   MU      67601        1
3      2003   MU      67640        3
4      2001   MC      33058        1
5      2002   MC      34564        9
6      2003   MC      46834       16

what I would like to acheive is a vjust value based on the Team. In the following, MU would be vjust=1 and MC would be vjust=-1 so I can control where the data label is located from the data group with which it is associated.

I've tried to hack around a couple of examples that use a function containing a lookup table (it's not a straight ifelse as I have many values for Team) but I can't seem to pass a string to the function through the aes method along these lines:

lut <- list(MU=1,MC=-1)
vj <-function(x){lut[[x]]}
p=ggplot(df, aes(YearStart, Attendance, label=Position, group=Team))+
   geom_point()+
   geom_text(aes(vjust = vj(Team) ) )
print(p)

The following is pseudo(ish)code which applies the labels twice to each group in each location above and below the points.

p=ggplot(df, aes(YearStart, Attendance, label=Position, group=Team))+
   geom_point()+
   geom_text(aes(Team="MU"), vjust=1)+
   geom_text(aes(Team="MC"), vjust=-1)
print(p)

I've tried several other strategies for this and I can't tell whether I'm trying this from the wrong direction or I'm just missing a very trivial piece of ggplot syntax. I've accomplished a stop-gap solution by labelling them manually in Excel but that's not sustainable :-)

2
  • Please don't edit your question to refer to answers. This gets very confusing. If you wish to clarify certain points, then by all means do that. If you wish to comment on an answer, then the appropriate place is in the comments following the answer. Commented Nov 15, 2011 at 15:16
  • I have reverted the question, since this is more clear. However, prior to doing that, I noticed an error in your new code. Remember that R is case sensitive, and you used Offset in your data.frame but offset in the ggplot call. Commented Nov 15, 2011 at 15:30

1 Answer 1

5

To specify an aesthetic, that aesthetic should be a column in your data.frame.

(Notice also that your lookup function should have single brackets, not double.)

And a final thought: vjust and hjust are strictly only defined between [0, 1] for left/bottom and right/top justification. In practise, however, it is usually possible to extend this. I find that settings of (-0.2, 1.2) work quite well, in most cases.

lut <- list(MU=-0.2, MC=1.2)
vj <- function(x) lut[x]

df$offset <- vj(df$Team)

library(ggplot2)
ggplot(df, aes(YearStart, Attendance, label=Position, group=Team)) +
    geom_point(aes(colour=Team)) +
    geom_text(aes(vjust = offset))

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

Looks great - it all runs but I still get the default vjust=0.5 being applied. My figure looks like this one but with the labels over the points, and with no warnings or errors in stdout.
Have you checked that df$offset contains the correct values?
You have made a typo. Remember that R is case sensitive. You used Offset in the data.frame, but offset in the ggplot code.
No change. Typo corrected - I'm using capital O for Offset throughout for consistency and df$Offset contains (1,2,1.2,1.2,-0.2,-0.2,-0.2) as one would hope. Still getting the label overlaying the numbers but at least it's only making one pass rather labelling both above and below. Sorry about the mis-editing and thanks for the guidance - I'm still getting the hang of how this clever site works.
Hardwire the Offset as a 6th column in the dataframe thus: Offset <- c(-1,-1,-1,1,1,1) has removed the need for the lookup table function and fits better with the back-end data extraction too. Once again, thanks for the guidance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.