Any way to extend the line in the legend? - r

Let us say I have the following graph plotted using ggplot:
Is there anyway to extend how much line length is displayed in the legend? Sometimes, it just gets impossible to identify which line correspond to which line in the graph using the legend.

here is an option legend.key.width:
# sample data frame
df <- data.frame(x = c(rnorm(100, -3), rnorm(100), rnorm(100, 3)),
g = gl(3, 100))
df <- ddply(df, .(g), summarize, x = x, y = ecdf(x)(x))
ggplot(df, aes(x, y, colour = g, linetype = g)) +
geom_line() +
theme(legend.key.width = unit(10, "line"))

opts is not working with ggplot2. You need to use theme, so instead you need to type:
+ theme(legend.key.width = unit(10, "line"))

Related

ggplot - Find coordinates of facet spacing

I have, e.g., the following plot:
library(ggplot2)
dat = data.frame(x = rnorm(100), y = rexp(100), grp = factor(sample(1:2, 100, replace = TRUE)))
ggplot(dat, aes(x = x, y = y, color = grp)) +
geom_point() +
facet_wrap(~grp) +
theme(panel.spacing = unit(2, "lines"))
and want to add a vertical line between the two plots - that is, in the middle of the panel spacing. My problem is, I am not sure of how to get the coordinates of the inner plot edges / the panel spacing in native units.
Both panels have unit 0.5 npc -- and I am not sure how I would convert this. I tried using viewports, but that did not work. Is there a way other than arranging plot 1 - plot of vertical line - plot 2 ?
Is this what you had in mind? You can tweak around with the parameter to change the position where the line will appear.
# loading the libraries
library(ggplot2)
library(grid)
library(cowplot)
# preparing the data
dat = data.frame(x = rnorm(100),
y = rexp(100),
grp = factor(sample(1:2, 100, replace = TRUE)))
# preparing the plot
plot <- ggplot(dat, aes(x = x, y = y, color = grp)) +
geom_point() +
facet_wrap( ~ grp) +
theme(panel.spacing = unit(2, "lines"))
# preparing the line
gline <- grid::linesGrob(x = 0.5)
# plotting both the plot and the line
cowplot::ggdraw() +
cowplot::draw_plot(plot) +
cowplot::draw_plot(gline)
Created on 2018-01-24 by the reprex
package (v0.1.1.9000).
library(grid)
library(gtable)
library(magrittr)
ggplotGrob(p) %>%
gtable_add_grob(segmentsGrob(0.5, 0, 0.5, 1),
t = 4, b = 8, l = 7, r = 7) %>%
grid.draw()
enter image description here

Add labels above top axis in ggplot2 graph while keeping original x axis on bottom

I'm trying to add some labels to a ggplot2 boxplot to indicate the number of observations, and I'd like that annotation to appear above the top axis of the graph. I can add them inside the graph pretty easily, and I suspect there's an application of ggplot_gtable that might do this, but I don't understand how to use that (a point in the direction of a good tutorial would be much appreciated). Here's some example data with labels:
Count <- sample(100:500, 3)
MyData <- data.frame(Category = c(rep("A", Count[1]), rep("B", Count[2]),
rep("C", Count[3])),
Value = c(rnorm(Count[1], 10),
rnorm(Count[2], 20),
rnorm(Count[3], 30)))
MyCounts <- data.frame(Category = c("A", "B", "C"),
Count = Count)
MyCounts$Label <- paste("n =", MyCounts$Count)
ggplot(MyData, aes(x = Category, y = Value)) +
geom_boxplot() +
annotate("text", x = MyCounts$Category, y = 35,
label = MyCounts$Label)
What I'd love is for the "n = 441" and other labels to appear above the graph rather than just inside the upper boundary. Any suggestions?
Rather than separately calculating the counts, you can add the counts with geom_text and the original data frame (MyData). The key is that we need to add stat="count" inside geom_text so that counts will be calculated and can be used as the text labels.
theme_set(theme_classic())
ggplot(MyData, aes(x = Category, y = Value)) +
geom_boxplot() +
geom_text(stat="count", aes(label=paste0("n=",..count..)), y=1.05*max(MyData$Value)) +
expand_limits(y=1.05*max(MyData$Value))
To put the labels above the plot, add some space above the plot area for the text labels and then use the code in the answer linked by #aosmith to override clipping:
library(grid)
theme_set(theme_bw())
p = ggplot(MyData, aes(x = Category, y = Value)) +
geom_boxplot() +
geom_text(stat="count", aes(label=paste0("n=",..count..)),
y=1.06*max(MyData$Value), size=5) +
theme(plot.margin=margin(t=20))
# Override clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

ggplot multiple lines colored as gradient

I'm currently struggling to wrap my head around the following objective:
a 2x2 facet grid
in each facet a couple of lines
each line colored according to some continuous variable
I not even get the simple example working. So far I have:
df <- data.frame(xval = rep(1:5, 8),
yval = runif(40),
pval = rep(c(rep(1,5), rep(2, 5)),4),
plt = rep(c(rep("mag", 10), rep("ph", 10)), 2),
p = c(rep("p1", 20), rep("p2", 20))
)
ggplot(df, aes(xval, yval)) +
geom_line(aes(colour = pval)) +
facet_grid(plt~p)
Would very much appreciate your help.
Since pval is not a factor variable you need to specify the grouping explicitly.
ggplot(df, aes(xval, yval)) +
geom_line(aes(colour = pval, group = pval)) +
facet_grid(plt~p)

Colour lines by mean of value pairs in ggplot2

When mapping colour to lines in ggplot2, e.g.:
x = data.frame(x = 1:6, y = c(0,0,10,10,0,0))
ggplot(x, aes(x, y, col=y)) + geom_line(size=5)
.. the lines colours are mapped to the first data point of each line segment. Is there any easy way to get ggplot to calculate the mean value of both points instead (ie. so the sloping lines are both scaled to the colour for 5)?
Similar idea as #Richard, but use the zoo package.
library(zoo)
x = data.frame(x = 1:6, y = c(0,0,10,10,0,0))
ggplot(x, aes(x, y, col=rollmean(y, 2, fill = 0))) + geom_line(size=5)
Does this do what you want?
x = data.frame(x = 1:6, y = c(0,0,10,10,0,0))
x$c <- rowMeans(cbind(x$y, c(x$y[-1], NA)))
ggplot(x, aes(x, y, col=c)) + geom_line(size=5)

Different size facets at x-axis

Length of x-axis is important for my plot because it allows one to compare between facets, therefore I want facets to have different x-axis sizes. Here is my example data:
group1 <- seq(1, 10, 2)
group2 <- seq(1, 20, 3)
x = c(group1, group2)
mydf <- data.frame (X =x , Y = rnorm (length (x),5,1),
groups = c(rep(1, length (group1)), rep(2, length(group2))))
And my code:
p1 = ggplot(data=mydf,aes(x=X,y=Y,color=factor(groups)) )+
geom_point(size=2)+
scale_x_continuous(labels=comma)+
theme_bw()
p1+facet_grid(groups ~ .,scales = "fixed",space="free_x")
And the resulting figure:
Panel-1 has x-axis values less then 10 whereas panel-2 has x-axis value extending to 20. Still both panels and have same size on x-axis. Is there any way to make x-axis panel size different for different panels, so that they correspond to their (x-axis) values?
I found an example from some different package that shows what I am trying to do, here is the figure:
Maybe something like this can get you started. There's still some formatting to do, though.
library(grid)
library(gridExtra)
library(dplyr)
library(ggplot2)
p1 <- ggplot(data=mydf[mydf$groups==1,],aes(x=X,y=Y))+
geom_point(size=2)+
theme_bw()
p2 <- ggplot(data=mydf[mydf$groups==2,],aes(x=X,y=Y))+
geom_point(size=2)+
theme_bw()
summ <- mydf %>% group_by(groups) %>% summarize(len=diff(range(X)))
summ$p <- summ$len/max(summ$len)
summ$q <- 1-summ$p
ng <- nullGrob()
grid.arrange(arrangeGrob(p1,ng,widths=summ[1,3:4]),
arrangeGrob(p2,ng,widths=summ[2,3:4]))
I'm sure there's a way to make this more general, and the axes don't line up perfectly yet, but it's a beginning.
Here is a solution following OP's clarifying comment ("I guess axis will be same but the boxes will be of variable size. Is it possible by plotting them separately and aligning in grid?").
library(plyr); library(ggplot2)
buffer <- 0.5 # Extra space around the box
#Calculate box parameters
mydf.box <- ddply(mydf, .(groups), summarise,
max.X = max(X) + buffer,
min.X = 0,
max.Y = max(Y) + buffer,
min.Y = 0,
X = mean(X), Y = mean(Y)) #Dummy values for X and Y needed for geom_rect
p2 <- ggplot(data=mydf,aes(x=X, y=Y) )+
geom_rect(data = mydf.box, aes( xmax = max.X, xmin = min.X,
ymax = max.Y, ymin = min.Y),
fill = "white", colour = "black", fill = NA) +
geom_point(size=2) + facet_grid(groups ~ .,scales = "free_y") +
theme_classic() +
#Extra formatting to make your plot like the example
theme(panel.background = element_rect(fill = "grey85"),
strip.text.y = element_text(angle = 0),
strip.background = element_rect(colour = NA, fill = "grey65"))

Resources