user20061
user20061

Reputation: 554

How to dodge points in ggplot2 in R

df = data.frame(subj=c(1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10), block=factor(rep(c(1,2),10)), acc=c(0.75,0.83,0.58,0.75,0.58,0.83,0.92,0.83,0.83,0.67,0.75,0.5,0.67,0.83,0.92,0.58,0.75,0.5,0.67,0.67))
ggplot(df,aes(block,acc,group=subj)) + geom_point(position=position_dodge(width=0.3)) + ylim(0,1) + labs(x='Block',y='Accuracy')

How do I get points to dodge each other uniformly in the horizontal direction? (I grouped by subj in order to get it to dodge at all, which might not be the correct thing to do...)

Upvotes: 3

Views: 3927

Answers (2)

G_T
G_T

Reputation: 1587

I think this might be what you were looking for, although no doubt you have solved it by now. Hopefully it will help someone else with the same issue.

A simple way is to use geom_dotplot like this:

ggplot(df,aes(x=block,y=acc)) + 
geom_dotplot(binaxis = "y", stackdir = "center", binwidth = 0.03)  + ylim(0,1) + labs(x='Block',y='Accuracy')

This looks like this:

geom_dotplot example

Note that x (block in this case) has to be a factor for this to work.

Upvotes: 4

Ram Narasimhan
Ram Narasimhan

Reputation: 22506

If they don't have to be perfectly aligned horizontally, here's one quick way of doing it, using geom_jitter. You don't need to group by subj.

Method 1 [Simpler]: Using geom_jitter()

ggplot(df,aes(x=block,y=acc)) + geom_jitter(position=position_jitter(0.05)) + ylim(0,1) + labs(x='Block',y='Accuracy')

Play with the jitter width for greater degree of jittering.

which produces:

enter image description here

Method 2: Deterministically calculating the jitter value for each row

We first use aggregate to count the number of duplicated entries. Then in a new data frame, for each duplicated value, move it horizontally to the left by an epsilon distance.

df$subj <- NULL #drop this so that aggregate works.

#a new data frame that shows duplicated values
agg.df <- aggregate(list(numdup=seq_len(nrow(df))), df, length)
agg.df$block <- as.numeric(agg.df$block) #block is not a factor
#      block  acc numdup
#1     2      0.50      2
#2     1      0.58      2
#3     2      0.58      1
#4     1      0.67      2
#...    
epsilon <- 0.02 #jitter distance

new.df <- NULL #create an expanded dataframe, with block value jittered deterministically
r <- 0
for (i in 1:nrow(agg.df)) {
  for (j in 1:agg.df$numdup[i]) {
    r <- r+1 #row counter in the expanded df
    new.df$block[r] <- agg.df$block[i]
    new.df$acc[r] <- agg.df$acc[i]
    new.df$jit.value[r] <- agg.df$block[i] - (j-1)*epsilon    
  }
}
new.df <- as.data.frame(new.df)
ggplot(new.df,aes(x=jit.value,y=acc)) + geom_point(size=2) + ylim(0,1)  + labs(x='Block',y='Accuracy') + xlim(0,3)

which produces:

enter image description here

Upvotes: 1

Related Questions