Related
I am making a line plot of several groups and want to make a visualization where one of the groups lines are highlighted
ggplot(df) + geom_line(aes(x=timepoint ,y=var, group = participant_id, color=color)) +
scale_color_identity(labels = c(red = "g1",gray90 = "Other"),guide = "legend")
However, the group lines are partially obscured by the other groups lines
How can I make these lines always on top of other groups lines?
The simplest way to do this is to plot the gray and red groups on different layers.
First, let's try to replicate your problem with a dummy data set:
set.seed(1)
df <- data.frame(
participant_id = rep(1:50, each = 25),
timepoint = factor(rep(0:24, 50)),
var = c(replicate(50, runif(1, 50, 200) + runif(25, 0.3, 1.5) *
sin(0:24/(0.6*pi))^2/seq(0.002, 0.005, length = 25))),
color = rep(sample(c("red", "gray90"), 50, TRUE, prob = c(1, 9)), each = 100)
)
Now we apply your plotting code:
library(ggplot2)
ggplot(df) +
geom_line(aes(x=timepoint ,y=var, group = participant_id, color = color)) +
scale_color_identity(labels = c(red = "g1", gray90 = "Other"),
guide = "legend") +
theme_classic()
This looks broadly similar to your plot. If instead we plot in different layers, we get:
ggplot(df, aes(timepoint, var, group = participant_id)) +
geom_line(data = df[df$color == "gray90",], aes(color = "Other")) +
geom_line(data = df[df$color == "red",], aes(color = "gl")) +
scale_color_manual(values = c("red", "gray90")) +
theme_classic()
Created on 2022-06-20 by the reprex package (v2.0.1)
You can use factor releveling to bring the line (-s) of interest to front.
First, let's plot the data as is, with the red line partly hidden by others.
library(ggplot2)
library(dplyr)
set.seed(13)
df <-
data.frame(timepoint = rep(c(1:100), 20),
participant_id = paste0("p_", sort(rep(c(1:20), 100))),
var = abs(rnorm(2000, 200, 50) - 200),
color = c(rep("red", 100), rep("gray90", 1900)))
ggplot(df) +
geom_line(aes(x = timepoint ,
y = var,
group = participant_id, color = color)) +
scale_color_identity(labels = c(red = "g1", gray90 = "Other"),
guide = "legend")
Now let's bring p_1 to front by making it the last factor level.
df %>%
mutate(participant_id = factor(participant_id)) %>%
mutate(participant_id = relevel(participant_id, ref = "p_1")) %>%
mutate(participant_id = factor(participant_id, levels = rev(levels(participant_id)))) %>%
ggplot() +
geom_line(aes(x=timepoint,
y=var,
group = participant_id,
color = color)) +
scale_color_identity(labels = c(red = "g1", gray90 = "Other"),
guide = "legend")
I try to limit the x-axis of a plot with several figures to the current week. So if we are now in week 45 all weeks from 1 till 45 should be displayed, but not from 46 onwards. I cannot get any xlim command to work e.g. xlim(1,45) returns Error:
Discrete value supplied to continuous scale.
Perhaps this has to do with the fact that the variable week is a factor, but this is necessary for correct plotting (no decimals). Any solutions?
set.seed(1)
dat <- data.frame(object = sample(c("A","B","C","D"),100,replace = TRUE),
week = sample(c(1:52),100,replace = TRUE),
year = sample(c(2016,2017,2018),100,replace = TRUE),
count = sample(c(0:10),100,replace = TRUE))
ggplot(dat, aes(factor(week), count )) +
geom_bar(stat="identity" , aes(fill = factor(year)), position = position_dodge2(width = 0.9, preserve = "single")) +
facet_wrap(~ object, ncol = 2, scales = "free_y") +
labs(x = "Week", y = "Count") +
scale_fill_discrete(name = "Year")
You can restrict in data itself.
Try with the below code :
data<-dat%>% filter(week < format(Sys.Date(),"%V")) ## filtering based on current week
Plotting :
ggplot(data, aes(factor(week), count )) +
geom_bar(stat="identity" , aes(fill = factor(year)), position = position_dodge2(width = 0.9, preserve = "single")) +
facet_wrap(~ object, ncol = 2, scales = "free_y") +
labs(x = "Week", y = "Count") +
scale_fill_discrete(name = "Year") +theme(axis.text.x = element_text(angle = 45, vjust = 0.4))
Why not add a filter before the plot call for week:
set.seed(1)
dat <- data.frame(object = sample(c("A","B","C","D"),100,replace = TRUE),
week = sample(c(1:52),100,replace = TRUE),
year = sample(c(2016,2017,2018),100,replace = TRUE),
count = sample(c(0:10),100,replace = TRUE))
dat %>%
filter(week <= 45) %>% # add filter before plot
ggplot(aes(factor(week), count )) +
geom_bar(stat="identity" , aes(fill = factor(year)), position = position_dodge2(width = 0.9, preserve = "single")) +
facet_wrap(~ object, ncol = 2, scales = "free_y") +
labs(x = "Week", y = "Count") +
scale_fill_discrete(name = "Year")
In this SO answer, user #Crops shows how to add a legend to a ggalt::geom_dumbbell plot. Very nice.
library(ggalt)
df <- data.frame(trt=LETTERS[1:5], l=c(20, 40, 10, 30, 50), r=c(70, 50, 30, 60, 80))
df2 = tidyr::gather(df, group, value, -trt)
ggplot(df, aes(y = trt)) +
geom_point(data = df2, aes(x = value, color = group), size = 3) +
geom_dumbbell(aes(x = l, xend = r), size=3, color="#e3e2e1",
colour_x = "red", colour_xend = "blue",
dot_guide=TRUE, dot_guide_size=0.25) +
theme_bw() +
scale_color_manual(name = "", values = c("red", "blue") )
I want to sort trt descending on r. I tried replacing y = trt with y = reorder(trt, r), but I get an error that object r is not found.
Here is a way where we reorder the factor levels of trt in df and df2 before we plot.
# reorder factor levels
df$trt <- reorder(df$trt, df$r)
df2$trt <- factor(df2$trt, levels = levels(df$trt))
ggplot(df, aes(y = trt)) +
geom_point(data = df2, aes(x = value, color = group), size = 3) +
geom_dumbbell(aes(x = l, xend = r), size=3, color="#e3e2e1",
colour_x = "red", colour_xend = "blue",
dot_guide=TRUE, dot_guide_size=0.25) +
theme_bw() +
scale_color_manual(name = "", values = c("red", "blue") )
Using the dumbbell package
##Reformat data
df3<-df %>% arrange(r)
df2<-df%>% mutate("key"="trt")
df2$trt<-factor(df2$trt,df3$trt)
##plot
dumbbell::dumbbell(df2, id="trt", column1="l", column2="r",key="key", delt =1, textsize=3, lab1 = "l", lab2="r", pt_val = 1, pointsize = 3,pt_alpha = 0.6, arrow=1, leg = "Add legend title", pval=2) + xlim(8,85) + facet_wrap(key ~.)
Added in some bells and whistles, you can remove them toggling with the options.
I dont have enough points to embed for here is the link. Hope someone finds it useful.
I search in R implementation (may be html widget on java script) a stacked bar chart in ribbon style, which allows you to see the rating change for each category in the dynamics.
It's look like ribbon chart in power bi desktop
Search rseek.org gave no results.
First off: Not a fan of that ribbon-styled stacked bar chart at all; while colourful and stylish, it's difficult to synthesise the relevant information. But that's just my opinion.
You could try building a similar plot in ggplot2 using geom_ribbon. See below for a minimal example:
# Sample data
set.seed(2017);
one <- sample(5:15, 10);
two <- rev(one);
df <- cbind.data.frame(
x = rep(1:10, 2),
y = c(one, two),
l = c(one - 1, two - 1),
h = c(one + 1, two + 1),
id = rep(c("one", "two"), each = 10));
require(ggplot2);
ggplot(df, aes(x = x, y = y)) +
geom_ribbon(aes(ymin = l, ymax = h, fill = id), alpha = 0.4) +
scale_fill_manual(values = c("#E69F00", "#56B4E9"));
If you need interactivity, you could wrap it inside plotly::ggplotly.
Using ggsankey package.
In the following you can make use of smooth argument geom_sankey_bump to control the look/feel of the chart as in ribbon chart of Power BI.
df <- data.frame (model = c("A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J"),
Year = c(2015,2015,2015,2015,2015,2015,2015,2015,2015,2015,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2018,2018,2018,2018,2018,2018,2018,2018,2018,2018),
sales = c(450,678,456,344,984,456,234,244,655,789,234,567,234,567,232,900,1005,1900,450,345,567,235,456,345,144,333,555,777,111,444,222,223,445,776,331,788,980,1003,456,434))
#install.packages("remotes")
#remotes::install_github("davidsjoberg/ggsankey")
library(ggsankey)
library(tidyverse)
ggplot(df, aes(x = Year,
node = model,
fill = model,
value = sales)) +
geom_sankey_bump(space = 0, type = "alluvial", color = "transparent", smooth = 15) +
scale_fill_viridis_d(option = "A", alpha = .8) +
theme_sankey_bump(base_size = 16) +
labs(x = NULL,
y = "Sales ($ ths)",
fill = "Model",
color = NULL) +
theme(legend.position = "bottom") +
labs(title = "Sales per model per year")
On suggestion in comments, I tried replicating some of the features of power BI chart.
# Prepare some data
set.seed(1)
df <- data.frame(
occupation = rep(c("Clerical", "Management", "Manual", "Professional", "Skilled"), 12),
Month = factor(rep(month.abb, 5), levels = month.abb, ordered = TRUE),
Sales = sample(200:1000, 60, replace = TRUE)
)
df %>%
group_by(Month) %>%
mutate(Max = sum(Sales)) %>%
ungroup() %>%
mutate(Max = max(Sales)) %>%
ggplot(aes(x = Month,
node = occupation,
fill = occupation,
value = Sales)) +
geom_col(aes(x = Month, y = Max/1.2),
alpha = 0.5,
fill = 'grey',
width = 0.4) +
geom_sankey_bump(space = 15,
type = "alluvial",
color = "transparent",
smooth = 8,
alpha = 0.8) +
scale_fill_brewer(palette = "Set3") +
theme_minimal() +
labs(x = NULL,
y = "Sales ($ ths)",
fill = "Occupation",
color = NULL) +
theme(legend.position = "top") +
labs(title = "Sales per occupation per month")
Created on 2022-07-07 by the reprex package (v2.0.1)
You may find your answers with ggalluvial package.
https://cran.r-project.org/web/packages/ggalluvial/vignettes/ggalluvial.html
I have seen lots of question regarding converting count on y axis into percent but must of them are in bar plot.
I want to do similar thing in histogram but not able to show the labels on the bar clearly. Please tell me where I am doing wrong.
x = runif(100, min = 0, max = 10)
data1 <- data.frame(x = x)
ggplot(aes(x = x), data = data1)+
geom_histogram(aes(y = (..count..)/sum(..count..)), bins = 10, breaks =
seq(0,10,1), fill = "blue", col = "black")+
geom_text(aes(y = ((..count..)/sum(..count..)),
label = scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -10)+
scale_y_continuous(labels = scales::percent)
Output:
Use scale_y_continous with breaks and labels will solve your problem.
data1 <- data.frame (x = runif(100, min = 0, max = 10))
ggplot(aes(x=x), data1) + stat_bin(aes(y = ..count..))
ggplot(data1, aes(x = x)) + geom_histogram(fill = "blue", col = "black")+ scale_y_continuous(breaks = seq(0,10,1),labels = paste(seq(0, 10, by = 1) / 100, "%", sep = ""))+geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="green",vjust=2)
or, you can specify where you would like to add the percentage like this:
geom_text(aes(y = (..count..)+0.5))
of course you can change the color as well. from,
stat="bin",colour="your prefer color "
Also you can change the width of the bins as follows:
geom_histogram(fill = "blue", col = "black", binwidth = 0.5)