Issue when passing variable with dollar sign notation ($) to aes() in combination with facet_grid() or facet_wrap()
tl;dr
Never use [
or $
inside aes()
.
Consider this illustrative example where the facetting variable f
is purposely in a non-obvious order with respect to x
d <- data.frame(x=1:10, f=rev(letters[gl(2,5)]))
Now contrast what happens with these two plots,
p1 <- ggplot(d) +
facet_grid(.~f, labeller = label_both) +
geom_text(aes(x, y=0, label=x, colour=f)) +
ggtitle("good mapping")
p2 <- ggplot(d) +
facet_grid(.~f, labeller = label_both) +
geom_text(aes(d$x, y=0, label=x, colour=f)) +
ggtitle("$ corruption")
We can get a better idea of what's happening by looking at the data.frame created internally by ggplot2 for each panel,
ggplot_build(p1)[["data"]][[1]][,c("x","PANEL")]
x PANEL
1 6 1
2 7 1
3 8 1
4 9 1
5 10 1
6 1 2
7 2 2
8 3 2
9 4 2
10 5 2
ggplot_build(p2)[["data"]][[1]][,c("x", "PANEL")]
x PANEL
1 1 1
2 2 1
3 3 1
4 4 1
5 5 1
6 6 2
7 7 2
8 8 2
9 9 2
10 10 2
The second plot has the wrong mapping, because when ggplot creates a data.frame for each panel, it picks x values in the "wrong" order.
This occurs because the use of $
breaks the link between the various variables to be mapped (ggplot must assume it's an independent variable, which for all it knows could come from an arbitrary, disconnected source). Since the data.frame in this example is not ordered according to the factor f
, the subset data.frames used internally for each panel assume the wrong order.
facet_wrap plotting incorrect x axis co-ordinates
ggplot
has a data
argument for a reason. When you re-specify the data frame inside aes()
, it overrides the subsetting and ordering done for the faceting. Just don't re-specify the name of the data frame (no mydata$column
) and everything works fine:
ggplot(ZoutliersM,
aes(x = leftPos,
y = as.numeric(Def.x),
xend = leftPos,
yend = 0)) +
geom_point(fill = "magenta", size = 2, colour = "red") +
facet_wrap(~chr)
Now we can see that in the "22" facet, the point is a little under 10M, as expected.
Two other notes:
specifying a "fill" for
geom_point
won't do anything unless you also use a shape that has separate fill and colors, such asshape = 21
In your
dput
data,Def.x
is already numeric, so you don't need to convert it. If it was a factor previously, make sure you convert withas.numeric(as.character(Def.x))
, otherwise you'll simply be taking the levels rather than the value to numeric.
Wrong colour when using facet_wrap()
Don't use $
notation in ggplot
aesthetics. Use raw variable names instead:
qplot(a,b,data=df,geom='point',color=factor(c)) +
facet_wrap(~d) +
scale_colour_manual(values=c("blue","orange"))
facet_grid weird rearrangement of values
Do it like here (in aes
fill
should be the column NAME not the VECTOR):
plot <- ggplot(mockdata, aes(variable, Measurement, fill = plotval)) +
geom_tile(colour = "dark red") +
facet_grid(category~type, scales='free', space='free') +
scale_fill_gradient2(limits=c(-20, 20),high = "firebrick3", low = "dodgerblue4") +
theme_minimal() +
theme(axis.text.x=element_text(size=28, angle=90),
axis.text.y=element_text(size=28, face = "italic"),
strip.text.x=element_blank(),
strip.text.y=element_text(size=20, angle=0)) +
labs(title="", x="", y="", fill="")
ggplot facet_grid data.table order bug
Just remove all dat.rel$ inside the plot configuration makes the facet_grids work like desired, indipendently from the row order.
Problem with ggplot when reassigning variables for data
ggplot2 saves the data.frame passed to the data
parameter in the ggplot object. For anything referenced in aes
that is not in this data.frame it has to rely on scoping to find it when the plot is build (each time it is printed).
So, just make sure that resp
is passed to the data
parameter, too.
resp <- iris$Sepal.Length
p <- ggplot(cbind(iris, resp), aes(x = Petal.Length, y = resp))+
geom_point()
p
resp <- iris$Sepal.Width
p
#same plot
PS: Your example with the function works, because the plot environment of q1
and q2
are environments created during the function call whereas the plot environment of p
is the global environment. Compare p$plot_env
and q1$plot_env
and check out ls(q1$plot_env)
.
Issue when passing variable with dollar sign notation ($) to aes() in combination with facet_grid() or facet_wrap()
tl;dr
Never use [
or $
inside aes()
.
Consider this illustrative example where the facetting variable f
is purposely in a non-obvious order with respect to x
d <- data.frame(x=1:10, f=rev(letters[gl(2,5)]))
Now contrast what happens with these two plots,
p1 <- ggplot(d) +
facet_grid(.~f, labeller = label_both) +
geom_text(aes(x, y=0, label=x, colour=f)) +
ggtitle("good mapping")
p2 <- ggplot(d) +
facet_grid(.~f, labeller = label_both) +
geom_text(aes(d$x, y=0, label=x, colour=f)) +
ggtitle("$ corruption")
We can get a better idea of what's happening by looking at the data.frame created internally by ggplot2 for each panel,
ggplot_build(p1)[["data"]][[1]][,c("x","PANEL")]
x PANEL
1 6 1
2 7 1
3 8 1
4 9 1
5 10 1
6 1 2
7 2 2
8 3 2
9 4 2
10 5 2
ggplot_build(p2)[["data"]][[1]][,c("x", "PANEL")]
x PANEL
1 1 1
2 2 1
3 3 1
4 4 1
5 5 1
6 6 2
7 7 2
8 8 2
9 9 2
10 10 2
The second plot has the wrong mapping, because when ggplot creates a data.frame for each panel, it picks x values in the "wrong" order.
This occurs because the use of $
breaks the link between the various variables to be mapped (ggplot must assume it's an independent variable, which for all it knows could come from an arbitrary, disconnected source). Since the data.frame in this example is not ordered according to the factor f
, the subset data.frames used internally for each panel assume the wrong order.
error: ggplot2 facet is plotting incorrect values
The key is to adjust the data before calling ggplot() and not to keep calling "df$" inside ggplot. Otherwise certain errors are more likely to happen (e.g. factor orders can get mixed). To fix that in this case, you can try this:
require(ggplot2)
df$exp_fit <- exp(df$fit)
df$exp_lower <- exp(df$lower)
df$exp_upper <- exp(df$upper)
df$Type <- as.factor(df$Type)
df$ZQVT <- as.factor(df$ZQVT)
ggplot(df, aes(x=ZMemScore, y=exp_fit,
color=Type)) +
geom_ribbon(aes(ymin=exp_lower, ymax=exp_upper,
color=NA, fill=Type),
linetype=1, alpha=0.3) +
geom_line(aes(linetype=Type), size=1.2) +
xlab("ZMemScore") + ylab("Predicted RT (ms)") +
labs(color="Type", subtitle="ZQVT") +
facet_grid(. ~ ZQVT) +
scale_linetype_discrete(name='Type', labels=c('Nonword','Real Word')) +
theme_classic() +
scale_color_manual(values=c("black","firebrick2")) +
theme(plot.subtitle = element_text(hjust=0.5)) +
theme(text = element_text(size=14))+
guides(fill=FALSE, color=FALSE)
Output:
Sample data:
require(data.table)
df <- fread("ZMemScore ZQVT Type fit se lower upper
-1 -2 LDTNW 7.029661 0.04961080 6.932423 7.126900
0 -2 LDTNW 7.130045 0.03618878 7.059115 7.200976
1 -2 LDTNW 7.230430 0.05005473 7.132321 7.328538
2 -2 LDTNW 7.330814 0.07777387 7.178375 7.483253
-1 -1 LDTNW 6.953625 0.03015198 6.894526 7.012723
0 -1 LDTNW 7.021205 0.02288979 6.976340 7.066069
1 -1 LDTNW 7.088784 0.03319670 7.023718 7.153851
2 -1 LDTNW 7.156364 0.05141379 7.055592 7.257137
-1 0 LDTNW 6.877588 0.02308945 6.832332 6.922844
0 0 LDTNW 6.912364 0.01719115 6.878669 6.946059
1 0 LDTNW 6.947139 0.02335335 6.901366 6.992912
2 0 LDTNW 6.981915 0.03581413 6.911718 7.052111
-1 1 LDTNW 6.801552 0.03651265 6.729986 6.873117
0 1 LDTNW 6.803523 0.02498816 6.754545 6.852500
1 1 LDTNW 6.805494 0.02890588 6.748837 6.862150
2 1 LDTNW 6.807465 0.04434635 6.720545 6.894385
-1 2 LDTNW 6.725515 0.05752647 6.612762 6.838269
0 2 LDTNW 6.694682 0.03886592 6.618504 6.770860
1 2 LDTNW 6.663848 0.04441321 6.576797 6.750899
2 2 LDTNW 6.633015 0.06852165 6.498711 6.767319
-1 -2 LDTRW 6.903851 0.04518178 6.815294 6.992409
0 -2 LDTRW 6.972785 0.03334094 6.907436 7.038134
1 -2 LDTRW 7.041719 0.04585878 6.951835 7.131603
2 -2 LDTRW 7.110653 0.07082106 6.971842 7.249464
-1 -1 LDTRW 6.806363 0.02755119 6.752362 6.860364
0 -1 LDTRW 6.855938 0.02116456 6.814455 6.897421
1 -1 LDTRW 6.905514 0.03046645 6.845799 6.965229
2 -1 LDTRW 6.955089 0.04690274 6.863158 7.047020
-1 0 LDTRW 6.708874 0.02124658 6.667230 6.750518
0 0 LDTRW 6.739091 0.01594271 6.707843 6.770339
1 0 LDTRW 6.769308 0.02146327 6.727240 6.811377
2 0 LDTRW 6.799525 0.03272497 6.735384 6.863667
-1 1 LDTRW 6.611386 0.03344309 6.545836 6.676935
0 1 LDTRW 6.622244 0.02302851 6.577108 6.667381
1 1 LDTRW 6.633103 0.02646563 6.581230 6.684976
2 1 LDTRW 6.643962 0.04035829 6.564858 6.723065
-1 2 LDTRW 6.513897 0.05253701 6.410923 6.616871
0 2 LDTRW 6.505397 0.03572626 6.435373 6.575422
1 2 LDTRW 6.496898 0.04058913 6.417342 6.576453
2 2 LDTRW 6.488398 0.06223723 6.366411 6.610384")
ggplot2 faceting - plots not reordered when labels reordered
The factor
levels
reordering that you used seems to work with that small example at least:
library(ggplot2)
dtf <- data.frame(day = c("Mon", "Tue", "Wed", "Thu",
"Fri", "Sat", "Sun"),
value = 1:7)
ggplot(dtf, aes(x = value, y = value)) +
geom_point() + facet_wrap(~day)
dtf$day1 <- factor(dtf$day, levels = c("Mon", "Tue", "Wed", "Thu",
"Fri", "Sat", "Sun"))
ggplot(dtf, aes(x = value, y = value)) +
geom_point() + facet_wrap(~day1)
Let's have a look at the structure of the data frame:
str(dtf)
# 'data.frame': 7 obs. of 3 variables:
# $ day : Factor w/ 7 levels "Fri","Mon","Sat",..: 2 6 7 5 1 3 4
# $ value: int 1 2 3 4 5 6 7
# $ day1 : Factor w/ 7 levels "Mon","Tue","Wed",..: 1 2 3 4 5 6 7
Values are the same but the order of factor levels has been changed.
Related Topics
How to Sort a Data Frame by Alphabetic Order of a Character Variable in R
How to Dplyr Rename a Column, by Column Index
How to Find the Difference in Value in Every Two Consecutive Rows in R
How Does the 'Prop.Table()' Function Work in R
How to Make a Great R Reproducible Example
How to Find the Statistical Mode
Split Column At Delimiter in Data Frame
How to Name Variables on the Fly
Splitting a Dataframe into Several Dataframes
Convert Dataframe Column to 1 or 0 for "True"/"False" Values and Assign to Dataframe
I Want to Split Street Address into Two Columns. One With Street Number Other With Street Name
How to Join (Merge) Data Frames (Inner, Outer, Left, Right)
Remove Rows With All or Some Nas (Missing Values) in Data.Frame
How to Debug "Contrasts Can Be Applied Only to Factors With 2 or More Levels" Error