Manually changing line size in ggplot - r

Still getting to grips with ggplot. My question: How do I manually change the line size? I've tried with scale_size_manual but it didn't seem to work.
setup:
test.mat <- data.frame(matrix(nrow=32, ncol =3))
test.mat[,1] = rep(1:16,2)
test.mat[1:16,2] = as.character(rep("Cohort Alpha"),16)
test.mat[17:32,2] = as.character(rep("Factor Alpha"), 16)
test.mat[,3] = rnorm(32,0,1)
colnames(test.mat) = c("Window", "type", "value")
ggplot(test.mat, aes(x=Window, y=value)) +
geom_line(aes(colour = type, linetype = type)) +
theme_classic() +
scale_colour_manual("type", values = c("black", "steelblue")) +
scale_linetype_manual("type", values = c("solid", "solid")) +
scale_size_manual("type", values = c(5, 1.4), guide = "none")

specify size inside aes() function as follows:
ggplot(test.mat, aes(x=Window, y=value)) +
geom_line(aes(colour = type, linetype = type, size = type)) +
theme_classic() +
scale_colour_manual("type", values = c("black", "steelblue")) +
scale_linetype_manual("type", values = c("solid", "solid")) +
scale_size_manual("type", values = c(5, 1.4), guide = "none")

Just turning #NelsonGon comment into an answer.
Is this what you want?
test.mat <- data.frame(matrix(nrow=32, ncol =3))
test.mat[,1] = rep(1:16,2)
test.mat[1:16,2] = as.character(rep("Cohort Alpha"),16)
test.mat[17:32,2] = as.character(rep("Factor Alpha"), 16)
test.mat[,3] = rnorm(32,0,1)
colnames(test.mat) = c("Window", "type", "value")
# -------------------------------------------------------------------------
base <- ggplot(test.mat, aes(x=Window, y=value))
#Here is where you need to add size
line_size <- base + geom_line(aes(colour = type, linetype = type), size=3)
line_size + theme_classic() +
scale_colour_manual("type", values = c("black", "steelblue")) +
scale_linetype_manual("type", values = c("solid", "solid")) +
scale_size_manual("type", values = c(5, 1.4), guide = "none")
output
Update
If you want variable thickness for the individual lines, you can do as follows.
base <- ggplot(test.mat, aes(x=Window, y=value))
#Use an ifelse to add variable thickness
line_size <- base + geom_line(aes(colour = type, size=ifelse(type=="Cohort Alpha",1,2)))
line_size + guides(size = FALSE)

To follow up on my comment on deepseefan's answer
base +
geom_line(aes(colour = type,
size=factor(ifelse(type=="Cohort Alpha", "thick", "thin"),
levels=c("thick","thin")))) +
scale_colour_manual(values = c("black", "steelblue")) +
scale_size_manual(values = c(5, 1.4), guide = FALSE)

Related

How to use loop with geom_vline and facet_wrap?

I have data similar to the one I've created below:
set.seed(42)
dates <- seq.Date(as.Date("2012-08-01"), as.Date("2014-08-30"), "day")
n <- length(dates)
dat <- data.frame(date = dates,
category = rep(LETTERS[1:4], n/2),
daily_count = sample(18:100, n, replace=TRUE))
#following to be used for creating dotted lines; highlighting a certain point for each category
point_dates <- sample(seq.Date(as.Date("2012-08-01"), as.Date("2014-08-30"), "month"),4)
category_name <- list("A", "B", "C", "D")
I am creating a boxplot for each category using facet_wrap, and point_dates are important for me as they shows the point of interest in each boxplot. This is how I am creating the plot:
ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"), linetype=1, colour="red", size = 0.5)+
sapply(point_dates[[1]], function(xint) geom_vline(data=filter(dat,
category==category_name[[1]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
sapply(point_dates[[2]], function(xint) geom_vline(data=filter(dat,
category==category_name[[2]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
sapply(point_dates[[3]], function(xint) geom_vline(data=filter(dat,
category==category_name[[3]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
sapply(point_dates[[4]], function(xint) geom_vline(data=filter(dat,
category==category_name[[4]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
facet_wrap(~category, nrow = 2)
And this is the output of the code:
The plot is being created just fine. My question is, is there any better way (loop may be?) that would help me get rid of writing sapply multiple times. Because the number of categories may change (increase/decrease), that would be to change the code everytime.
Any guidance please?
I'm not sure that this is the best way, but you could do all of them in one go using map2 from tidyr. This would save you time from having to write out individual sapply.
library(tidyverse)
ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"),
linetype=1, colour="red", size = 0.5)+
map2(point_dates, category_name,
~geom_vline(data=filter(dat, category==.y),
aes(xintercept = .x),
linetype=3, colour="black", size = 1))+
facet_wrap(~category, nrow = 2)
You can use map() to iterate the calls to sapply():
ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"), linetype=1, colour="red", size = 0.5)+
map(seq_along(unique(dat$category)), ~sapply(point_dates[[.]], function(xint) geom_vline(data=filter(dat,
category==category_name[[.]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))) +
facet_wrap(~category, nrow = 2)
If i got it correct, you have already defined the dates for each group. So make the first plot:
library(ggplot2)
library(tsibble)
g = ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"), linetype=1, colour="red", size = 0.5)+
facet_wrap(~category, nrow = 2)
You just need to provide a new data frame and call geom_vline:
tmp = data.frame(category=unlist(category_name),date=point_dates)
g + geom_vline(data=tmp,aes(xintercept = date),
linetype=3, colour="black", size = 1)

Editing graph using ggpattern in R

I wrote some code to make a graph (both below)
p <- ggplot(for_plots, aes(x = factor(condition), y = conflict, fill = smoking_status)) +
stat_summary(fun = "mean", geom = "bar", position = "dodge") +
theme_classic() +
scale_fill_manual(labels = c("Smokers", "Ex"),
values = c("blue", "gold"), guide = "legend", (title = "Smoking status")) +
scale_color_manual(labels = c("Smokers", "Ex"),
values = c("blue", "gold"), guide = "legend", (title = "Smoking status")) +
labs(x = 'Condition', y = 'Conflict (AUC)') +
scale_x_discrete(labels = c('Animal','Smoking')) +
coord_cartesian(ylim=c(0,1.5)) +
scale_y_continuous(expand = c(0,0))
p +
stat_summary(fun.data = mean_se, geom = "errorbar", width = .08, position = position_dodge(0.9))
However, I recently read about 'ggpattern' and wondered if anyone could help me add some diagonal black lines to the yellow bars in my plot (e.g. ex-smokers conflict). I have tried multiple ways, but adding 'geom_col_pattern' to the code seems to mess up the Y axis and provide overall conflict for each condition (animal, smoking) rather than separately for smokers and ex-smokers. I think the 'geom_col_pattern' perhaps is not compatible with the 'stat_summary' I have in my code. Does anyone have any suggestions?
Thank you
Instead of adding a geom_col_pattern on top of your plot, just update the geom argument of stat_summary.
#replicate of your dataframe
for_plots <- data.frame(matrix(nrow = 100, ncol=0))
for_plots$condition <- sample(rep(c("Animal", "Smoking"), 100), 100)
for_plots$smoking_status <- sample(rep(c("Smokers", "Ex"), 100), 100)
n_smoking <- length(which(for_plots$condition == "Smoking"))
for_plots$conflict[for_plots$condition=="Smoking"] <- sample(seq(0.8, 1.3, length.out = n_smoking), n_smoking)
n_animal <- length(which(for_plots$condition == "Animal"))
for_plots$conflict[for_plots$condition=="Animal"] <- sample(seq(0.5, 1, length.out = n_animal), n_animal)
p <- ggplot(for_plots, aes(x = factor(condition), y = conflict, fill = smoking_status)) +
stat_summary(aes(pattern=smoking_status),
fun = "mean", position = "dodge",
geom = "bar_pattern", pattern_fill="black", colour="black") + #edited part
theme_classic() +
scale_fill_manual(labels = c("Smokers", "Ex"),
values = c("blue", "gold"), guide = "legend", (title = "Smoking status")) +
scale_color_manual(labels = c("Smokers", "Ex"),
values = c("blue", "gold"), guide = "legend", (title = "Smoking status")) +
labs(x = 'Condition', y = 'Conflict (AUC)') +
scale_pattern_manual(values=c("none", "stripe"))+ #edited part
scale_x_discrete(labels = c('Animal','Smoking')) +
coord_cartesian(ylim=c(0,1.5)) +
scale_y_continuous(expand = c(0,0))
p +
stat_summary(fun.data = mean_se, geom = "errorbar", width = .08, position = position_dodge(0.9))

Aesthetics must be either length 1 or the same as the data (1): x, y, label

I'm working on some data on party polarization (something like this) and used geom_dumbbell from ggalt and ggplot2. I keep getting the same aes error and other solutions in the forum did not address this as effectively. This is my sample data.
df <- data_frame(policy=c("Not enough restrictions on gun ownership", "Climate change is an immediate threat", "Abortion should be illegal"),
Democrats=c(0.54, 0.82, 0.30),
Republicans=c(0.23, 0.38, 0.40),
diff=sprintf("+%d", as.integer((Democrats-Republicans)*100)))
I wanted to keep order of the plot, so converted policy to factor and wanted % to be shown only on the first line.
df <- arrange(df, desc(diff))
df$policy <- factor(df$policy, levels=rev(df$policy))
percent_first <- function(x) {
x <- sprintf("%d%%", round(x*100))
x[2:length(x)] <- sub("%$", "", x[2:length(x)])
x
}
Then I used ggplot that rendered something close to what I wanted.
gg2 <- ggplot()
gg2 <- gg + geom_segment(data = df, aes(y=country, yend=country, x=0, xend=1), color = "#b2b2b2", size = 0.15)
# making the dumbbell
gg2 <- gg + geom_dumbbell(data=df, aes(y=country, x=Democrats, xend=Republicans),
size=1.5, color = "#B2B2B2", point.size.l=3, point.size.r=3,
point.color.l = "#9FB059", point.color.r = "#EDAE52")
I then wanted the dumbbell to read Democrat and Republican on top to label the two points (like this). This is where I get the error.
gg2 <- gg + geom_text(data=filter(df, country=="Government will not control gun violence"),
aes(x=Democrats, y=country, label="Democrats"),
color="#9fb059", size=3, vjust=-2, fontface="bold", family="Calibri")
gg2 <- gg + geom_text(data=filter(df, country=="Government will not control gun violence"),
aes(x=Republicans, y=country, label="Republicans"),
color="#edae52", size=3, vjust=-2, fontface="bold", family="Calibri")
Any thoughts on what I might be doing wrong?
I think it would be easier to build your own "dumbbells" with geom_segment() and geom_point(). Working with your df and changing the variable refences "country" to "policy":
library(tidyverse)
# gather data into long form to make ggplot happy
df2 <- gather(df,"party", "value", Democrats:Republicans)
ggplot(data = df2, aes(y = policy, x = value, color = party)) +
# our dumbell
geom_path(aes(group = policy), color = "#b2b2b2", size = 2) +
geom_point(size = 7, show.legend = FALSE) +
# the text labels
geom_text(aes(label = party), vjust = -1.5) + # use vjust to shift text up to no overlap
scale_color_manual(values = c("Democrats" = "blue", "Republicans" = "red")) + # named vector to map colors to values in df2
scale_x_continuous(limits = c(0,1), labels = scales::percent) # use library(scales) nice math instead of pasting
Produces this plot:
Which has some overlapping labels. I think you could avoid that if you use just the first letter of party like this:
ggplot(data = df2, aes(y = policy, x = value, color = party)) +
geom_path(aes(group = policy), color = "#b2b2b2", size = 2) +
geom_point(size = 7, show.legend = FALSE) +
geom_text(aes(label = gsub("^(\\D).*", "\\1", party)), vjust = -1.5) + # just the first letter instead
scale_color_manual(values = c("Democrats" = "blue", "Republicans" = "red"),
guide = "none") +
scale_x_continuous(limits = c(0,1), labels = scales::percent)
Only label the top issue with names:
ggplot(data = df2, aes(y = policy, x = value, color = party)) +
geom_path(aes(group = policy), color = "#b2b2b2", size = 2) +
geom_point(size = 7, show.legend = FALSE) +
geom_text(data = filter(df2, policy == "Not enough restrictions on gun ownership"),
aes(label = party), vjust = -1.5) +
scale_color_manual(values = c("Democrats" = "blue", "Republicans" = "red")) +
scale_x_continuous(limits = c(0,1), labels = scales::percent)

Create legend with manual shapes and colours

I use bars and line to create my plot. The demo code is:
timestamp <- seq(as.Date('2010-01-01'),as.Date('2011-12-01'),by="1 mon")
data1 <- rnorm(length(timestamp), 3000, 30)
data2 <- rnorm(length(timestamp), 30, 3)
df <- data.frame(timestamp, data1, data2)
p <- ggplot()
p <- p + geom_histogram(data=df,aes(timestamp,data1),colour="black",stat="Identity",bindwidth=10)
p <- p + geom_line(data=df,aes(timestamp,y=data2*150),colour="red")
p <- p + scale_y_continuous(sec.axis = sec_axis(~./150, name = "data2"))
p <- p + scale_colour_manual(name="Parameter", labels=c("data1", "data2"), values = c('black', 'red'))
p <- p+ scale_shape_manual(name="Parameter", labels=c("data1", "data2"), values = c(15,95))
p
This results in a plot like this:
This figure does not have a legend. I followed this answer to create a customized legend but it is not working in my case. I want a square and line shape in my legend corresponding to bars and line. How can we get it?
I want legend as shown in below image:
For the type of data you want to display, geom_bar is a better fit then geom_histogram. When you to manipulate the appaerance of the legend(s), you need to place the colour = ... parts inside the aes. To get the desired result it probably best to use different types of legend for the line and the bars. In that way you are better able to change the appearance of the legends with guide_legend and override.aes.
A proposal for your problem:
ggplot(data = df) +
geom_bar(aes(x = timestamp, y = data1, colour = "black"),
stat = "Identity", fill = NA) +
geom_line(aes(x = timestamp, y = data2*150, linetype = "red"), colour = "red", size = 1) +
scale_y_continuous(sec.axis = sec_axis(~./150, name = "data2")) +
scale_linetype_manual(labels = "data2", values = "solid") +
scale_colour_manual(name = "Parameter\n", labels = "data1", values = "black") +
guides(colour = guide_legend(override.aes = list(colour = "black", size = 1),
order = 1),
linetype = guide_legend(title = NULL,
override.aes = list(linetype = "solid",
colour = "red",
size = 1),
order = 2)) +
theme_minimal() +
theme(legend.key = element_rect(fill = "white", colour = NA),
legend.spacing = unit(0, "lines"))
which gives:

ggplot - Remove alpha legend

I have created a plot with the following dataset:
Locus;Island;AR;Type;Shapetype
MS1;ST;4,6315;MS;NA
MS1;FG;3,9689;MS;NA
MS1;SN;3;MS;NA
MS2;ST;2;MS;NA
MS2;FG;2;MS;NA
MS2;SN;2;MS;NA
MS3;ST;7,5199;MS;NA
MS3;FG;5,5868;MS;NA
MS3;SN;3;MS;NA
MS4;ST;2,9947;MS;NA
MS4;FG;3;MS;NA
MS4;SN;2;MS;NA
MS5;ST;9,0726;MS;NA
MS5;FG;5,6759;MS;NA
MS5;SN;2,963;MS;NA
MS6;ST;6,5779;MS;NA
MS6;FG;5,6842;MS;NA
MS6;SN;2;MS;NA
MS7;ST;2;MS;NA
MS7;FG;1;MS;NA
MS7;SN;1;MS;NA
MS8;ST;3,97;MS;NA
MS8;FG;2,9032;MS;NA
MS8;SN;1;MS;NA
MS9;ST;2;MS;NA
MS9;FG;1,9977;MS;NA
MS9;SN;2;MS;NA
MS10;ST;3,9733;MS;NA
MS10;FG;3,9971;MS;NA
MS10;SN;2;MS;NA
MS11;ST;7,4172;MS;NA
MS11;FG;5,6471;MS;NA
MS11;SN;3;MS;NA
MS12;ST;2;MS;NA
MS12;FG;2;MS;NA
MS12;SN;2;MS;NA
MS13;ST;5,6135;MS;NA
MS13;FG;3;MS;NA
MS13;SN;2;MS;NA
MT;ST;12;MT;NA
MT;FG;3;MT;NA
MT;SN;2;MT;NA
TLR1LA;ST;3,68;TLR;TLR1LA
TLR1LA;FG;4,4;TLR;TLR1LA
TLR1LA;SN;1;TLR;TLR1LA
TLR1LB;ST;3,99;TLR;TLR1LB
TLR1LB;FG;5;TLR;TLR1LB
TLR1LB;SN;1;TLR;TLR1LB
TLR2A;ST;4,9;TLR;TLR2A
TLR2A;FG;5;TLR;TLR2A
TLR2A;SN;2;TLR;TLR2A
TLR2B;ST;5,64;TLR;TLR2B
TLR2B;FG;4;TLR;TLR2B
TLR2B;SN;3;TLR;TLR2B
TLR3;ST;1;TLR;TLR3
TLR3;FG;3;TLR;TLR3
TLR3;SN;3;TLR;TLR3
TLR4;ST;1;TLR;TLR4
TLR4;FG;2,89;TLR;TLR4
TLR4;SN;2;TLR;TLR4
TLR5;ST;2,9;TLR;TLR5
TLR5;FG;2;TLR;TLR5
TLR5;SN;2;TLR;TLR5
TLR21;ST;2,91;TLR;TLR21
TLR21;FG;1;TLR;TLR21
TLR21;SN;1;TLR;TLR21
Here's the code for the plot:
ggplot(comb, aes(Island, AR, group = Locus, colour = (factor(Type)))) +
geom_line(aes(colour = factor(Type), alpha = factor(Type), size = factor(Type))) +
scale_alpha_manual(values = c("MS"=0.2, "MT"=0.2, "TLR" = 1)) +
scale_size_manual(values = c("MS"=0.5, "MT"=0.5, "TLR" = 0.3)) +
xlab("Island") +
ylab("Allelic Richness") +
scale_x_discrete(labels = c("Santiago", "Fogo", "Sao Nicolau"),
limits = c("ST", "FG", "SN")) +
geom_point(aes(shape = (factor(Shapetype)))) +
scale_shape_manual(values = c(1,2,3,4,5,6,7,8,9,10),
breaks=c("TLR1LA","TLR1LB","TLR2A","TLR2B","TLR3",
"TLR4", "TLR5","TLR21", "MS", "MT")) +
scale_colour_manual(values = c("Red","Blue","Black"),
breaks=c("TLR1LA","TLR1LB","TLR2A","TLR2B","TLR3",
"TLR4","TLR5","TLR21", "MS", "MT")) +
theme_bw() +
labs(shape="Functional", colour="Neutral")
The plot is okay, however, I need to remove the legend that is created for the alpha values. I have tried to use both + scale_alpha(guide = 'none')and guide = 'none', but none of them seem to work (I may be placing them in the wrong places, though). I suspect that they do not work, because of the manual adjustment of the alpha values.
Please be aware that this is not a minimal example.
Please note that your alpha legend is also your size legend, but this is very hard to see since your sizes are very similar. Set guide = 'none' in both scale_alpha_manual and scale_size_manual to remove that portion of the legend.
If you only do it in scale_alpha_manual you can actually see that the alpha becomes 1 for those lines, so it works as intended. So #Thierry's answer is correct.
Full code
ggplot(comb, aes(Island, AR, group = Locus, colour = (factor(Type)))) +
geom_line(aes(colour = factor(Type), alpha = factor(Type), size = factor(Type))) +
scale_alpha_manual(values = c("MS"=0.2, "MT"=0.2, "TLR" = 1), guide = 'none') +
scale_size_manual(values = c("MS"=0.5, "MT"=0.5, "TLR" = 0.3), guide = 'none') +
xlab("Island") +
ylab("Allelic Richness") +
scale_x_discrete(labels = c("Santiago", "Fogo", "Sao Nicolau"),
limits = c("ST", "FG", "SN")) +
geom_point(aes(shape = (factor(Shapetype)))) +
scale_shape_manual(values = c(1,2,3,4,5,6,7,8,9,10),
breaks=c("TLR1LA","TLR1LB","TLR2A","TLR2B","TLR3",
"TLR4", "TLR5","TLR21", "MS", "MT")) +
scale_colour_manual(values = c("Red","Blue","Black"),
breaks=c("TLR1LA","TLR1LB","TLR2A","TLR2B","TLR3",
"TLR4","TLR5","TLR21", "MS", "MT")) +
theme_bw() +
labs(shape="Functional", colour="Neutral")
Result
(Note that my y-axis is wrong because your data includes comma's and I was lazy.)
guide = "none" should do the trick
ggplot(
comb,
aes(Island, AR, group = Locus, colour = (factor(Type)))
) +
geom_line(aes(alpha = factor(Type), size = factor(Type))) +
geom_point(aes(shape = factor(Shapetype))) +
scale_x_discrete(
"Island",
labels = c("Santiago", "Fogo", "Sao Nicolau"),
limits = c("ST", "FG", "SN")
) +
ylab("Allelic Richness") +
scale_alpha_manual(values = c("MS"=0.2, "MT"=0.2, "TLR" = 1), guide = "none") +
scale_size_manual(values = c("MS"=0.5, "MT"=0.5, "TLR" = 0.3)) +
scale_shape_manual(
"Functional",
values = c(1,2,3,4,5,6,7,8,9,10),
breaks = c("TLR1LA","TLR1LB","TLR2A","TLR2B","TLR3","TLR4","TLR5","TLR21", "MS", "MT")
) +
scale_colour_manual(
"Neutral",
values = c("Red","Blue","Black"),
breaks = c("TLR1LA","TLR1LB","TLR2A","TLR2B","TLR3","TLR4","TLR5","TLR21", "MS", "MT")
) +
theme_bw()
Starting with this basic plot
bp <- df %>%
ggplot(aes(column_of_interest, alpha = 0.25)) + geom_density()
from r cookbook, where bp is your ggplot -
Remove legend for a particular aesthetic (alpha):
bp + guides(alpha="none")

Resources