ggplot facet_wrap: At least one layer must contain all variables used for facetting - facet-wrap

I am using the command
qplot(factor(ww), WeeklyYield, geom = "bar", fill = I("grey50"))+facet_wrap(~model+name)
to create a bar chart for every combination of model and name. However I get the following error message:
Error in layout_base(data, vars, drop = drop) :
At least one layer must contain all variables used for facetting
I cannot uncode this message.

I'm not sure if it still helps after so much time, but I suspect the problem is that you're feeding a formula into facet_wrap(), whereas it can only take a variable, e.g. facet_wrap(~model).
If you want a formula, try facet_grid() as an alternative, e.g. facet_grid(.~model+name).

Looks like ggplot does not found 'model' and /or 'name' column in your dataframe WeeklyYield.
You should check with names(WeeklyYield)

Related

Change colors to the 'fill' in aes?

I have this:
colr=c(a='black',b='red',c='brown')
Basically, i have used the fill with the categories from a column in the df in the aes. Thus it will show through the categories the plot. The problem is when i try to put the colr vector in the fill to change colors as it says it encounters the problem
Error: Aesthetics must be either length 1 or the same as the data (5): fill
Obviously the incorrect way of typing it makes it think that the colors refer to the brandscolumn while it should refer to the g_classes in the fill.
ggplot(df,aes(brands,fill=g_classes))+geom_bar(stat='count',fill=colr)
So, how to pass the colors in the colr vector to the fill (g_classes) in aes?
You have an option to use the scale_fill_manual command. It has to be the same length as you have categories, however. In this case it seems that you are attempting to specify three colours for five categories, and this is most likely why your code fails.
It is hard to reproduce your problem given the limited examples you give, but try omitting the fill argument in the geom_bar command, and changing the value for the stat argument to "identity"
Change your colour vector to
colr=c("black","red","brown")
and add additional ggplot line
scale_fill_manual(values=colr)+

ggplot2: Why symbol sizes differ when 'size' is including inside vs outside aes statement?

I have created quite a few maps using base-R but I am now trying to perform similar tasks using ggplot2 due to the ease by which multiple plots can be arranged on a single page. Basically, I am plotting the locations at which samples of a particular species of interest have been collected and want the symbol size to reflect the total weight of the species collected at that location. Creating the base map and various layers has not been an issue but I'm having trouble getting the symbol sizes and associated legend the way I want them.
The problem is demonstrated in the workable example below. When I include 'size' outside of aes, the symbol sizes appear to be scaled appropriately (plot1). But when I put 'size' inside the aes statement (in order to get a legend) the symbol sizes are no longer correct (plot2). It looks like ggplot2 has rescaled the data. This should be a simple task so I am clearly missing something very basic. Any help understanding this would be appreciated.
library(ggplot2)
#create a very simple dataset that includes locations and total weight of samples collected from each site
catch.data<-data.frame(long=c(-50,-52.5,-52,-54,-53.8,-52),
lat=c(48,54,54,55,52,50),
wt=c(2,38,3,4,25,122))
#including 'size' outside of aes results in no legend
#but the symbol sizes are represented correctly
plot1<-ggplot(catch.data,aes(x=long,y=lat)) +
geom_point(size=catch.data$wt,colour="white",fill="blue",shape=21)
#including 'size' within aes appears necessary in order to create a legend
#but the symbol sizes are not represented correctly
plot2<-ggplot(catch.data,aes(x=long,y=lat)) +
geom_point(aes(size=catch.data$wt),colour="white",fill="blue",shape=21)
First, you shouldn't reference the data frame name inside of aes, it messed the legend up. So the correct version will be
plot3 <- ggplot(catch.data,aes(x=long,y=lat)) +
geom_point(aes(size=wt),colour="white",fill="blue",shape=21)
Now in order to demonstrate variety you should play around with the range argument of scale_size_continuous, e.g.
plot3 + scale_size_continuous(range = range(catch.data$wt) / 5)
Change it a few times and see which one works for you. Please note that there exists a common visualization pitfall of representing numbers as areas (google e.g. "why pie charts are bad").
Edit: answering the comment below, you could introduce a fixed scaling by e.g.
scale_size_continuous(limits = c(1, 200), range = c(1, 20)).
Any value within the aes() is mapped to the variables in the data, while that is not the case for values specified outside the aes()
Refer to Difference between passing options in aes() and outside of it in ggplot2
Also the documentation : http://ggplot2.tidyverse.org/reference/aes.html

Make my y-axis values more legible

This is the code I have to create my gg-plot in R. It's not bad so far, in the sense that I successfully got it to be grouped by the correct principles and colour coded by classes. My problem is that rather than having a bunch of random y-values on the y-axis, I want an appropriate scale and bars to follow.
ggplot(SUMMARY.PCTDIFF, aes(principle, pctdiff)) +
geom_bar(aes(fill = class),position = "dodge", stat="identity",col="black")
Your pctdiff variable got turned into a factor by accident. Run
SUMMARY.PCTDIFF$pctdiff <- as.numeric(as.character(SUMMARY.PCTDIFF$pctdiff))
and recreate your plot. Even better, look upstream in your workflow and see how you can stop this from happening (hint, fix errors in your supposedly all-numeric column/use na.strings argument to read.csv/use stringsAsFactors=FALSE and then convert to numeric explicitly ...)

r ggplot - conditionally set aes element to NULL

I am building a wrapper function for ggplot to enable standard charts to be created with a single line of code.
One part of this is that in some cases the user will wish to set 'group' and 'color' aes elements, however in other cases they will not.
Is there a simple way of only having a 'group' or 'colour' aes element if the user passes one to the function, and to leave it blank otherwise?
I have tried simply setting these to to NULL, however this does not work, returning the following error.
Error: Aesthetics must be either length 1 or the same as the data (4): x, y, group, colour
Instead of NULL, try setting the aesthetic to 1.

Spatial plot error after changes to dataframe

I was using the following code to plot a spatial plot successfully:
colours<-(brewer.pal(7, "Blues"))
brks<-classIntervals(EDdata2$SIRt, n=7, style="fixed",fixedBreaks=c(0,1,2,5.0,10.0,20,50,120))
plot(brks, pal=colours)
brks<-brks$brks
plot(EDdata2, col=colours[findInterval(EDdata2$SIRt, brks,
all.inside=TRUE)], axes=F, border=FALSE)
However I made some changes to the spatialpolygonsdataframe EDdata2 by adding some extra columns and changing how SIRt is calculated (however it remains a column of numbers - they are just calculate differently)
Now when I try to run the plot code I get an error despite having made no changes to the plotting code:
Error in plot.default(...) : formal argument "axes" matched by multiple actual arguments
Whats going on here ?
That means that the package author of the unnamed package you used to create EDdata2 defined a plot method for whatever class EDdata2 might be that both used the axes argument and also used the triple dot mechanism to pass arguments to plot.default without filtering out that argument. (This does suggest that the package author didn't really want you to make your own axes, so you should investigate the help page for plot.whatever to see if it offers a mechanism for passing the values you want to use for 'at' and 'labels'.) You will need to do the spadework yourself (or edit your answer to make it more complete and reproducible) to investigate.
If this code is using the plot method for the SpatialPolygons-class in package:sp then the default value for axes is already FALSE.
help("SpatialPolygons-class", package="sp")
It is of course possible to mess this up by defining "F" to be something other than "FALSE" and then using axes=F. In the current instance it might be simpler to just remove that argument from the call.

Resources