Say I have function like:
quad <- function(x)
{
return (x^2)
}
That I plot using ggplot:
plot <- ggplot(data.frame(x=c(0,4)), aes(x = x)) +
stat_function(fun = quad)
So far, so good, but the line is really thin. I thus add some specific geometry to the line:
plot + geom_line(size=2)
But it returns this error:
Error: geom_line requires the following missing aesthetics: y
How can I manipulate line geometry in this type of graphs?
After playing around a while I found out that an argument named size can be passed into stat_function. It has the same effect as gem_line:
plot <- ggplot(data.frame(x=c(0,4)), aes(x = x)) +
stat_function(fun = quad, size=1.5)
Related
I am trying to plot two ´geom_vline()´ in a graph.
The code below works fine for one vertical line:
x=1:7
y=1:7
df1 = data.frame(x=x,y=y)
vertical.lines <- c(2.5)
ggplot(df1,aes(x=x, y=y)) +
geom_line()+
geom_vline(aes(xintercept = vertical.lines))
However, when I add the second desired vertical line by changing
vertical.lines <- c(2.5,4), I get the error:
´Error: Aesthetics must be either length 1 or the same as the data (7): xintercept´
How do I fix that?
Just remove aes() when you use + geom_vline:
ggplot(df1,aes(x=x, y=y)) +
geom_line()+
geom_vline(xintercept = vertical.lines)
It's not working because the second aes() conflicts with the first, it has to do with the grammar of ggplot.
You should see +geom_vline as a layer of annotation to the graph, not like +geom_points or +geom_line which are for mapping data to the plot. (See here how they are in two different sections).
All the aesthetics need to have either length 1 or the same as the data, as the error tells you. But the annotations can have different lengths.
Data:
x=1:7
y=1:7
df1 = data.frame(x=x,y=y)
vertical.lines <- c(2.5,4)
ggplot(df1, aes(x = x, y = y)) +
geom_line() +
sapply(vertical.lines, function(xint) geom_vline(aes(xintercept = xint)))
Histogram breaks
In base plot, when you use the hist function, it automatically calculates the breaks using the nclass.Sturges function, in ggplot however, you have to provide the breaks.
If I plot a histogram of the classical faithfull data I get the following graph:
data("faithful")
hist(faithful$waiting)
This works
I found out in this question, that you can mimic the
library(tidyverse)
data("faithful")
brx <- pretty(range(faithful$waiting), n = nclass.Sturges(faithful$waiting), min.n = 1)
ggplot(faithful, aes(waiting)) +
geom_histogram(color="darkgray", fill="white", breaks=brx)
But this does not
But I would like to add the breaks within my ggplot function, so I tried this:
ggplot(faithful, aes(waiting)) +
geom_histogram(color="darkgray", fill="white",
aes(breaks=pretty(range(waiting),
n = nclass.Sturges(waiting),
min.n = 1)))
Which gives me the following error:
Warning: Ignoring unknown aesthetics: breaks
Error: Aesthetics must be either length 1 or the same as the data (272): breaks, x
I understand what it means, but I can put Aesthetics of length one in aes, such as:
ggplot(faithful, aes(waiting)) +
geom_histogram(color="darkgray", fill="white", breaks=brx,
aes(alpha = 0.5))
What am I doing wrong?
geom_histogram uses the same aes as geom_bar according to the documentation and breaks isn't one of those aesthetics. (See geom_bar)
In the working code chunk you pass breaks to the function geom_histogram directly and that works, but in the problematic chunk you pass it as an aesthetic, and ggplot complains.
This works for me and I think does what you want:
ggplot(faithful, aes(x = waiting)) +
geom_histogram(color = "darkgray", fill = "white",
breaks = pretty(range(faithful$waiting),
n = nclass.Sturges(faithful$waiting),
min.n = 1))
I'm iterating through multiple data sets to produce line plots for each set. How can I prevent ggplot from complaining when I use geom_line over one point?
Take, for example, the following data:
mydata = data.frame(
x = c(1, 2),
y = c(2, 2),
group = as.factor(c("foo", "foo"))
)
Creating line graph looks and works just fine because there are two points in the line:
ggplot(mydata, aes(x = x, y = y)) +
geom_point() +
geom_line(aes(group = group))
However, plotting only the fist row give the message:
geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
ggplot(mydata[1,], aes(x = x, y = y)) +
geom_point() +
geom_line(aes(group = group))
Some of my figures will only have one point and the messages cause hangups in the greater script that produces these figures. I know the plots still work, so my concern is avoiding the message. I'd also like to avoid using suppressWarnings() if possible in case another legitimate and unexpected issue arises.
Per an answer to this question: suppressMessages(ggplot()) fails because you have to wrap it around a print() call of the ggplot object--not the ggplot object itself. This is because the warning/message only occurs when the object is drawn.
So, to view your plot without a warning message run:
p <- ggplot(mydata[1,], aes(x = x, y = y)) +
geom_point() +
geom_line(aes(group = group))
suppressMessages(print(p))
I think the following if-else solution should resolve the problem:
if (nrow(mydata) > 1) {
ggplot(mydata, aes(x = x, y = y)) +
geom_point() +
geom_line(aes(group = group))
} else {
ggplot(mydata, aes(x = x, y = y)) +
geom_point()
}
On the community.RStudio.com, John Mackintosh suggests a solution which worked for me:
Freely quoting:
Rather than suppress warnings, change the plot layers slightly.
Facet wrap to create empty plot
Add geom_point for entire data frame
Subset the dataframe by creating a vector of groups with more than one data point, and filtering the original data for those groups. Only
plot lines for this subset.
Details and example code in the followup of the link above.
I have data that I made a histogram for (ur_memr_t$up...). I then used fitdistr to fit an exponential dist to the data. I captured the parameters for the fitted distribution and generated some random variates. I then made a density curve for the exp random variates. I want to place the density over the histogram. The following code throws this error
exp_data <- data.frame( x = rexp(3000, rate = 0.0144896182))
ggplot(data = ur_memr_t, aes(ur_memr_t$updated_days_to_next_ur)) +
geom_histogram() + ggplot(exp_data, aes(x)) + geom_density()
Error in p + o : non-numeric argument to binary operator
In addition: Warning message:
Incompatible methods ("+.gg", "Ops.data.frame") for "+"
If I run
ggplot(data = ur_memr_t, aes(ur_memr_t$updated_days_to_next_ur)) +
geom_histogram()
and
ggplot(exp_data, aes(x)) + geom_density()
seperately, they produce correct plots. Why will they not work together and plot one on top of the other?
I think it should work but you can only have one ggplot statement. Try something like this:
g = ggplot(data = ur_memr_t, aes(updated_days_to_next_ur))
g = g + geom_histogram(aes(updated_days_to_next_ur))
g = g + geom_density(data = exp_data, aes(x))
Hope it helps
I have question probably similar to Fitting a density curve to a histogram in R. Using qplot I have created 7 histograms with this command:
(qplot(V1, data=data, binwidth=10, facets=V2~.)
For each slice, I would like to add a fitting gaussian curve. When I try to use lines() method, I get error:
Error in plot.xy(xy.coords(x, y), type = type, ...) :
plot.new has not been called yet
What is the command to do it correctly?
Have you tried stat_function?
+ stat_function(fun = dnorm)
You'll probably want to plot the histograms using aes(y = ..density..) in order to plot the density values rather than the counts.
A lot of useful information can be found in this question, including some advice on plotting different normal curves on different facets.
Here are some examples:
dat <- data.frame(x = c(rnorm(100),rnorm(100,2,0.5)),
a = rep(letters[1:2],each = 100))
Overlay a single normal density on each facet:
ggplot(data = dat,aes(x = x)) +
facet_wrap(~a) +
geom_histogram(aes(y = ..density..)) +
stat_function(fun = dnorm, colour = "red")
From the question I linked to, create a separate data frame with the different normal curves:
grid <- with(dat, seq(min(x), max(x), length = 100))
normaldens <- ddply(dat, "a", function(df) {
data.frame(
predicted = grid,
density = dnorm(grid, mean(df$x), sd(df$x))
)
})
And plot them separately using geom_line:
ggplot(data = dat,aes(x = x)) +
facet_wrap(~a) +
geom_histogram(aes(y = ..density..)) +
geom_line(data = normaldens, aes(x = predicted, y = density), colour = "red")
ggplot2 uses a different graphics paradigm than base graphics. (Although you can use grid graphics with it, the best way is to add a new stat_function layer to the plot. The ggplot2 code is the following.
Note that I couldn't get this to work using qplot, but the transition to ggplot is reasonably straighforward, the most important difference is that your data must be in data.frame format.
Also note the explicit mapping of the y aesthetic aes=aes(y=..density..)) - this is slighly unusual but takes the stat_function results and maps it to the data:
library(ggplot2)
data <- data.frame(V1 <- rnorm(700), V2=sample(LETTERS[1:7], 700, replace=TRUE))
ggplot(data, aes(x=V1)) +
stat_bin(aes(y=..density..)) +
stat_function(fun=dnorm) +
facet_grid(V2~.)