This question already has an answer here:
Custom colors for groups using ggplot2
(1 answer)
Closed 2 months ago.
Is there any command to set your own pallet?
In a plot like this:
library(ggalluvial)
library(ggplot2)
library(dplyr)
df <- data.frame(status = c("open", "close", "close", "open/close", "close"),
stock = c("google", "amazon", "amazon", "yahoo", "amazon"),
newspaper = c("times", "newyork", "london", "times", "times"))
# Count the number of occurance for each alluvial
df <- df %>% dplyr::group_by(stock, newspaper, status) %>%
summarise(n = n())
# Define the factors
df$status <- factor(df$status, levels = c("open", "open/close", "close"))
df$stock <- factor(df$stock, levels = c("google", "amazon", "yahoo"))
df$newspaper <- factor(df$newspaper, levels = c("times", "newyork", "london"))
# Plot the alluvial as in https://cran.r-project.org/web/packages/ggalluvial/vignettes/ggalluvial.html#alluvia-wide-format
ggplot2::ggplot(df.2, aes(y = n, axis1 = stock, axis2 = newspaper)) +
ggalluvial::geom_alluvium(aes(fill = status), width = 1/12) +
ggalluvial::geom_stratum(width = 1/12, fill = "black", color = "grey") +
ggplot2::geom_label(stat = "stratum", aes(label = after_stat(stratum))) +
ggplot2::scale_x_discrete(limits = c("stock", "newspaper"), expand = c(.05, .05)) +
ggplot2::scale_fill_brewer(type = "qual", palette = "Set1")
How is it possible to set our own colours?
You already are setting your own palette (you have chosen the "Set1" palette from the RColorBrewer package via scale_fill_brewer). If you want to set the colors manually, use scale_fill_manual
ggplot(df, aes(y = n, axis1 = stock, axis2 = newspaper)) +
geom_alluvium(aes(fill = status), width = 1/12) +
geom_stratum(width = 1/12, fill = "gray30", color = "white", size = 2) +
geom_text(stat = "stratum", aes(label = after_stat(stratum), angle = 90),
color = "white", size = 6) +
scale_x_discrete(limits = c("stock", "newspaper"), expand = c(.05, .05)) +
scale_fill_manual(values = c(open = 'red4',
`open/close` = 'orange3',
close ='navy')) +
ggtitle("Alluvial-Test") +
theme_void(base_size = 16) +
theme(plot.margin = margin(20, 20, 20, 20))
Related
I try to run this option of a plot:
library(ggalluvial)
library(ggplot2)
library(dplyr)
df <- data.frame(status = c("open", "close", "close", "open/close", "close"),
stock = c("google", "amazon", "amazon", "yahoo", "amazon"),
newspaper = c("times", "newyork", "london", "times", "times"))
# Count the number of occurance for each alluvial
df <- df %>% dplyr::group_by(stock, newspaper, status) %>%
summarise(n = n())
# Define the factors
df$status <- factor(df$status, levels = c("open", "open/close", "close"))
df$stock <- factor(df$stock, levels = c("google", "amazon", "yahoo"))
df$newspaper <- factor(df$newspaper, levels = c("times", "newyork", "london"))
# Plot the alluvial as in https://cran.r-project.org/web/packages/ggalluvial/vignettes/ggalluvial.html#alluvia-wide-format
ggplot2::ggplot(df.2, aes(y = n, axis1 = stock, axis2 = newspaper)) +
ggalluvial::geom_alluvium(aes(fill = status), width = 1/12) +
ggalluvial::geom_stratum(width = 1/12, fill = "black", color = "grey") +
ggplot2::geom_label(stat = "stratum", aes(label = after_stat(stratum))) +
ggplot2::scale_x_discrete(limits = c("stock", "newspaper"), expand = c(.05, .05)) +
ggplot2::scale_fill_brewer(type = "qual", palette = "Set1") +
ggplot2::ggtitle("Alluvial-Test")
Is there any command which can reduce the labels of this two columns stock and newspaper?
You could change the size in geom_label like this:
library(ggalluvial)
library(ggplot2)
library(dplyr)
df <- data.frame(status = c("open", "close", "close", "open/close", "close"),
stock = c("google", "amazon", "amazon", "yahoo", "amazon"),
newspaper = c("times", "newyork", "london", "times", "times"))
# Count the number of occurance for each alluvial
df <- df %>% dplyr::group_by(stock, newspaper, status) %>%
summarise(n = n())
#> `summarise()` has grouped output by 'stock', 'newspaper'. You can override
#> using the `.groups` argument.
# Define the factors
df$status <- factor(df$status, levels = c("open", "open/close", "close"))
df$stock <- factor(df$stock, levels = c("google", "amazon", "yahoo"))
df$newspaper <- factor(df$newspaper, levels = c("times", "newyork", "london"))
# Plot the alluvial as in https://cran.r-project.org/web/packages/ggalluvial/vignettes/ggalluvial.html#alluvia-wide-format
ggplot2::ggplot(df, aes(y = n, axis1 = stock, axis2 = newspaper)) +
ggalluvial::geom_alluvium(aes(fill = status), width = 1/12) +
ggalluvial::geom_stratum(width = 1/12, fill = "black", color = "grey") +
ggplot2::geom_label(stat = "stratum", aes(label = after_stat(stratum)), size = 2) +
ggplot2::scale_x_discrete(limits = c("stock", "newspaper"), expand = c(.05, .05)) +
ggplot2::scale_fill_brewer(type = "qual", palette = "Set1") +
ggplot2::ggtitle("Alluvial-Test")
#> Warning: Using the `size` aesthetic in this geom was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` in the `default_aes` field and elsewhere instead.
Created on 2022-12-11 with reprex v2.0.2
This is at least a known issue. And there are several solutions presented here. I personally like the solution with ggfittext. Here is how I tried to solve your problem. Note the solution by #Quinten is also very good:
We could fit the black color with alpha=...:
#install.packages("ggfittext")
library(ggfittext)
library(ggalluvial)
library(ggplot2)
library(dplyr)
# Plot the alluvial as in https://cran.r-project.org/web/packages/ggalluvial/vignettes/ggalluvial.html#alluvia-wide-format
ggplot2::ggplot(df, aes(y = n, axis1 = stock, axis2 = newspaper, label=after_stat(stratum))) +
ggalluvial::geom_alluvium(aes(fill = status), width = 1/12) +
geom_stratum(width = 1/12, fill="black", color="grey") +
ggfittext::geom_fit_text(stat = "stratum", width = 1/12, min.size = 3, color="grey") +
ggplot2::scale_x_discrete(limits = c("stock", "newspaper"), expand = c(.05, .05)) +
ggplot2::scale_fill_brewer(type = "qual", palette = "Set1") +
ggplot2::ggtitle("Alluvial-Test")
I think a nicer result would be obtained from geom_text at 90 degrees rotation:
ggplot(df, aes(y = n, axis1 = stock, axis2 = newspaper)) +
geom_alluvium(aes(fill = status), width = 1/12, color = "white", size = 2) +
geom_stratum(width = 1/12, fill = "gray30", color = "white", size = 2) +
geom_text(stat = "stratum", aes(label = after_stat(stratum), angle = 90),
color = "white", size = 8) +
scale_x_discrete(limits = c("stock", "newspaper"), expand = c(.05, .05)) +
scale_fill_brewer(type = "qual", palette = "Set1") +
ggtitle("Alluvial-Test") +
theme_void(base_size = 20) +
theme(plot.margin = margin(20, 20, 20, 20))
How can I add a main common legend to suitable blank area for facet_wrap plot? I need 3 line types with 3 different colors in the legend. (black dotted line: Current Price, green dotted line: lowline, red dotted line: highline)
Reproducible example:
library(quantmod)
library(purrr)
library(tidyverse)
library(stats)
start_date <- as.Date("2018-02-02")
end_date <- as.Date("2018-09-24")
adjustment <- TRUE
symbol <- c("AAPL", "AMZN", "MSFT")
getSymbols(symbol, src = "yahoo",
from = start_date, to=end_date,
adjust = adjustment)
DFCONVERT<- function (sym) {
library(xts)
newdata<-list()
newdata[[sym]]<-data.frame(Date=index(eval(as.symbol(sym))), coredata(eval(as.symbol(sym))))
columnnames<- c("Date", "Open", "High", "Low", "Close", "Volume", "Adjusted")
newdata[[sym]] <- newdata[[sym]] %>%
rename_with(~ gsub(paste0(sym, "."), '', .x))
}
symbol <- setNames(symbol, symbol)
newdata<-map_df(symbol, DFCONVERT, .id="symbol")
CurrentPrice=c(54.41500, 95.7505, 114.26)
lowline=c(40, 80, 98)
highline=c(50, 90, 110)
df<-data.frame(symbol, CurrentPrice, lowline, highline)
ggplot(newdata) +
geom_line(aes(Date,Close)) +
geom_hline(data = df, aes(yintercept = CurrentPrice), linetype = 'dotted', color="black")+
geom_hline(data = df, aes(yintercept = lowline), linetype = 'dashed', color="green")+
geom_hline(data = df, aes(yintercept = highline), linetype = 'dashed', color="red")+
facet_wrap(~symbol, scales = "free_y")+
theme(axis.text.x=element_text(size=8, angle=90,hjust=0.95,vjust=0.2))+
theme(axis.text.y=element_text(size=6))
If you want to have a legend the first step is to map on aesthetics instead of setting your color and linetypes as arguments, i.e. move color=... and linetype=... inside aes(). Second step is to set your desired colors and linetypes via scale_xxx_manual. Note, that to get only one legend we have to use the same name (which I simply set to NULL, i.e. no legend title) and the same labels:
library(ggplot2)
df <- data.frame(symbol, CurrentPrice, lowline, highline)
labels <- c("Current Price", "lowline", "highline")
names(labels) <- c("current", "low", "high")
ggplot(newdata) +
geom_line(aes(Date, Close)) +
geom_hline(data = df, aes(yintercept = CurrentPrice, linetype = "current", color = "current")) +
geom_hline(data = df, aes(yintercept = lowline, linetype = "low", color = "low")) +
geom_hline(data = df, aes(yintercept = highline, linetype = "high", color = "high")) +
scale_linetype_manual(values = c(current = "dotted", high = "dashed", low = "dashed"), labels = labels, name = NULL) +
scale_color_manual(values = c(current = "black", high = "red", low = "green"), labels = labels, name = NULL) +
facet_wrap(~symbol, scales = "free_y") +
theme(axis.text.x = element_text(size = 8, angle = 90, hjust = 0.95, vjust = 0.2)) +
theme(axis.text.y = element_text(size = 6))
I am doing the #duboischallenge and am on challenge 5.
I would like to remove the labels "0%" on the plot.
code (still learning so might not be most efficient code!):
income <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-02-16/income.csv')
data5 <- income %>%
gather(expenses, percentage, 3:7) %>%
mutate(percentage = replace_na(percentage, 0))
data5$expenses <- factor(data5$expenses, levels = c("Other", "Tax", "Clothes", "Food", "Rent"))
data5$Class <-factor(data5$Class, levels = c("Over $1000", "$750-1000", "$500-750", "$400-500", "$300-400", "$200-300", "$100-200"))
plot5 <-ggplot(data5, aes(x = Class, y = percentage, fill = expenses)) +
geom_bar(position = "fill", stat = "identity")+
scale_fill_manual(values = c("black", "blueviolet", "darksalmon", "azure3", "cornsilk3"), breaks = c("Rent", "Food","Clothes", "Tax", "Other"))+
geom_text(aes(x = Class, y = percentage, label = paste0(percentage, "%")), color = if_else(data5$expenses == "Rent", "white", "black"), size = 3.5, position = position_fill(vjust = 0.5)) +
coord_flip()
If I add
geom_text(data = data5 %>% filter(percentage > 3),aes(x = Class, y = percentage, label = paste0(percentage, "%")), color = if_else(data5$expenses == "Rent", "white", "black"), size = 3.5, position = position_fill(vjust = 0.5))
I get this error:
Error: Aesthetics must be either length 1 or the same as the data (32): colour
How do I remove the "0%" labels?
You can simply take the same approach like with colouring the labels:
ggplot(data5, aes(x = Class, y = percentage, fill = expenses)) +
geom_bar(position = "fill", stat = "identity")+
scale_fill_manual(values = c("black", "blueviolet", "darksalmon", "azure3", "cornsilk3"), breaks = c("Rent", "Food","Clothes", "Tax", "Other"))+
geom_text(aes(x = Class, y = percentage,
label = ifelse(percentage > 0, paste0(percentage, "%"), "")),
color = if_else(data5$expenses == "Rent", "white", "black"), size = 3.5, position = position_fill(vjust = 0.5)) +
coord_flip()
I have the following code that produce a ggplot that has text (i.e., "calibration") on both facets. I want the text be appeared on the first facet only. I tried a few things but didn't succeed. Any help would be appreciated.
library(ggplot2)
library(lubridate)
set.seed(123)
DF1 <- data.frame(Date = seq(as.Date("2001-01-01"), to = as.Date("2005-12-31"), by = "1 month"),
Ob = runif(60,1,5), L95 =runif(60, 0,4), U95 = runif(60,2,7), Sim = runif(60,1,5),
Loc = rep("Upstream", 60))
DF2 <- data.frame(Date = seq(as.Date("2001-01-01"), to = as.Date("2005-12-31"), by = "1 month"),
Ob = runif(60,1,5), L95 =runif(60, 0,4), U95 = runif(60,2,7), Sim = runif(60,1,5),
Loc = rep("Downstream", 60))
DF <- dplyr::bind_rows(DF1,DF2)
DF$Loc <- factor(DF$Loc, levels = c("Upstream","Downstream"))
ggplot(DF, aes(x = Date))+
geom_ribbon(aes(ymin = L95, ymax = U95), fill = "grey30", alpha = 0.4)+
geom_line(aes(y = Ob, color = "blue"), size = 1 )+
geom_line(aes(y = Sim, color = "black"), size = 1, linetype = "dashed")+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
facet_wrap(~ Loc, ncol = 1, scales = "free_y")+
theme_bw()+
annotate(geom = "text", x = as.Date("2002-01-01"), y = 4, label = "Calibration")
Try this trick:
library(ggplot2)
#Code
ggplot(DF, aes(x = Date))+
geom_ribbon(aes(ymin = L95, ymax = U95), fill = "grey30", alpha = 0.4)+
geom_line(aes(y = Ob, color = "blue"), size = 1 )+
geom_line(aes(y = Sim, color = "black"), size = 1, linetype = "dashed")+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
facet_wrap(~ Loc, ncol = 1, scales = "free_y")+
theme_bw()+
geom_text(data=data.frame(Date=as.Date("2002-01-01"),y=4,
label = "Calibration",Loc='Upstream'),
aes(y=y,label=label))
Output:
You can also use Loc=unique(DF$Loc)[1] in the geom_text() side. It will produce same output.
I'm making a plot with two different geoms, both use fill. I'd like one geom to have a legend, but the other to not. However adding show.legend=F to the required geom doesn't switch off the legend for that geom.
Example:
library(tidyverse)
library(ggalluvial)
x = tibble(qms = c("grass", "cereal", "cereal"),
move1 = "Birth",
move2 = c("Direct", "Market", "Slaughter"),
move3 = c("Slaughter", "Slaughter", NA),
freq = c(10, 5, 7))
x %>%
mutate(id = qms) %>%
to_lodes_form(axis = 2:4, id = id) %>%
na.omit() %>%
ggplot(aes(x = x, stratum = stratum, alluvium = id,
y = freq, label = stratum)) +
scale_x_discrete(expand = c(.1, .1)) +
geom_flow(aes(fill = qms)) +
geom_stratum(aes(fill = stratum), show.legend=F) +
geom_text(stat = "stratum", size = 3) +
theme_void() +
labs(fill="")
Output:
Desired output:
Question:
How do I turn off the fill legend for one geom, but not the other? I can (if I have to) do this in inkscape/gimp, but would prefer a solution I can version control.
Have a look at the final line of code:
scale_fill_discrete(breaks = c("grass", "cereal"))
That defines the breaks for the fills to only include cereal and grass, as required.
library(tidyverse)
library(ggalluvial)
x = tibble(qms = c("grass", "cereal", "cereal"),
move1 = "Birth",
move2 = c("Direct", "Market", "Slaughter"),
move3 = c("Slaughter", "Slaughter", NA),
freq = c(10, 5, 7))
x %>%
mutate(id = qms) %>%
to_lodes_form(axis = 2:4, id = id) %>%
na.omit() %>%
ggplot(aes(x = x, stratum = stratum, alluvium = id,
y = freq, label = stratum)) +
scale_x_discrete(expand = c(.1, .1)) +
geom_flow(aes(fill = qms)) +
geom_stratum(aes(fill = stratum), show.legend=FALSE) +
geom_text(stat = "stratum", size = 3) +
theme_void() +
labs(fill="") +
scale_fill_discrete(breaks = c("grass", "cereal")) #<- This line!
Created on 2019-03-18 by the reprex package (v0.2.1)