Arranging bars in ggplot2 stem plot - r

I am trying to arrange the bars in this stem plot from longest to shortest. This https://www.r-graph-gallery.com/301-custom-lollipop-chart/ suggests that i can use the arrange function before I pipe into the graph. I can't reproduce their example. The bars end up in a sort of random order. Any idea why the arrange is not working
mtcars %>%
mutate(mpg = as.numeric(mpg)) %>%
mutate(x = factor(rownames( mtcars))) %>%
arrange(mpg) %>%
ggplot( aes(x=x, y=mpg)) +
geom_segment( aes(x=x, xend=x, y=0, yend=mpg), color="skyblue", size=1) +
geom_point( color="blue", size=4, alpha=0.6) +
theme_light() +
coord_flip()

I'm writing this answer quickly on my phone so forgive me for not having testable code, but you need to change the order of the factor rather rather arranging the data frame.

Maybe if you arrange by mpg before creating your x variable.
mtcars %>%
mutate(mpg = as.numeric(mpg)) %>%
arrange(mpg) %>%
mutate(x = factor(rownames( mtcars), levels = rownames( mtcars))) %>%
ggplot( aes(x=x, y=mpg)) +
geom_segment( aes(x=x, xend=x, y=0, yend=mpg), color="skyblue", size=1) +
geom_point( color="blue", size=4, alpha=0.6) +
theme_light() +
coord_flip()

Related

How to incorporate legend as plot of plot size when arranging multiple plots using patchwork?

Dummy code:
library(ggplot2)
library(patchwork)
plot1 <- mpg %>% ggplot()
plot2 <- mpg %>% ggplot()
plot3 <- mpg %>% ggplot(aes(cyl, displ)) +
geom_point(aes(colour = manufacturer)) +
guides(colour=guide_legend(ncol=4))
(plot1 + plot2) / plot3
I'm not looking for a combined legend, but something which looks like:
Where the legend is 'considered' part of the plot. I've tried adding in margins with theme() and plot_spacer() but it's not exactly what I want. This is what I get:
For your example code one option would be to make use of guide_area() like so:
library(ggplot2)
library(patchwork)
library(magrittr)
plot1 <- mpg %>% ggplot()
plot2 <- mpg %>% ggplot()
plot3 <- mpg %>% ggplot(aes(cyl, displ)) +
geom_point(aes(colour = manufacturer)) +
guides(colour = guide_legend(ncol=3))
plot1 + plot2 + plot3 + guide_area() +
plot_layout(guides = 'collect')
Another option would be to extract the guide via cowplot::get_legend and add it to the patchwork like so:
(plot1 + plot2) / (plot3 + guides(color = "none") + cowplot::get_legend(plot3))
Created on 2021-09-22 by the reprex package (v2.0.1)

Pie chart with ggplot2 using data from read.csv2

I am trying to create a pie chart with ggplot. I want to show how many hours I use for diffrent tasks at work everyday.
# Libraries
library(ggplot2)
library(tidyverse) # function "%>%"
# 1. Read data (semicolon separated)
res = read.csv2(text = "Activity;No_of_Hours
Work;3
Lunch;1
Meetings;2
Talking;1")
# 2. Print table
df <- as.data.frame(res)
df
# 3. Plot Pie chart
res %>% ggplot(aes(x="", # we leave x blank with ""
y= Activity,
fill=No_of_Hours)) +
geom_bar(stat="identity") +
coord_polar("y", start=0) +
theme_classic()
You can calculate the y position of labels with coord_polar and plot them with geom_text
df <- df %>%
arrange(desc(Activity)) %>%
mutate(prop = No_of_Hours / sum(df$No_of_Hours) *100) %>%
mutate(ypos = cumsum(prop)- 0.5*prop )
# 3. Plot Pie chart
ggplot(df, aes(x="", y=prop, fill=Activity)) +
geom_bar(stat="identity", width=1, color="white") +
coord_polar("y", start=0) +
theme_void() +
geom_text(aes(y = ypos, label = No_of_Hours), color = "white", size=6)
which give you:
Or more similar to your example (but IMHO less informative):
ggplot(df, aes(x="", y=prop, fill=No_of_Hours)) +
geom_bar(stat="identity", width=1, color="white") +
coord_polar("y", start=0) +
theme_void() +
geom_text(aes(y = ypos, label =Activity ), color = "white", size=6)
which give you:

ggplot labels with "K" for thousands or "M" for millions (maintaining 'comma' y-axis labeling)

library(tidyverse)
df <- mpg %>% head() %>% mutate(hwy = hwy * 10000)
ggplot(df, aes(cty, hwy)) +
geom_point() +
scale_y_continuous(label = scales::comma) +
geom_text(aes(label = hwy), hjust = -0.25)
I want the labels on this plot to use "K" for thousands (eg 260K instead of 260000). BUT - I want to maintain the y-axis as is, with commas (eg 260,000). How can I achieve this?
You can use scales::label_number_si():
library(scales)
library(ggplot2)
ggplot(df, aes(cty, hwy)) +
geom_point() +
scale_y_continuous(label = comma) +
geom_text(aes(label = label_number_si()(hwy)), hjust = -0.25)
You can just add a custom column called myLabel to your dataframe which holds your desired labels. In the package scales you can find a function that does the converting part for you:
df <- mpg %>% head() %>% mutate(hwy = hwy * 10000)
df$myLabels <- scales::label_number_si()(df$hwy)
Now, use the new column myLabels as the aesthetic for creating the labels
ggplot(df, aes(cty, hwy)) +
geom_point() +
scale_y_continuous(label = scales::comma) +
geom_text(aes(label = myLabels), hjust = -0.25)

ggplot for one dependent variable and multiple indipendent

Is it possible to create multiple ggplots using facet_wrap when having y varaible always the same and just changing x variable:
Lets say we have:
library(ggplot2)
library(dplyr)
colnames(mtcars)
mtcars %>%
ggplot(aes(hp, mpg)) +
geom_point() +
geom_smooth(method = "lm")
mtcars %>%
ggplot(aes(hp, cyl)) +
geom_point() +
geom_smooth(method = "lm")
mtcars %>%
ggplot(aes(hp, disp)) +
geom_point() +
geom_smooth(method = "lm")
mtcars %>%
ggplot(aes(hp, drat)) +
geom_point() +
geom_smooth(method = "lm")
.
.
.
mtcars %>%
ggplot(aes(hp, carb)) +
geom_point() +
geom_smooth(method = "lm")
I know plots above can be create manually and then using grid arrange combined, however is there more efficient way?
With a little data augmentation, we can. We first create an "id" using row_number, and then use the gather function to go from a wide data set into a tall data set. We deselect the id and hp columns.
mtcars %>%
mutate(id = row_number()) %>%
gather(variable, value, -id, -hp) %>%
ggplot(aes(hp, value))+
geom_point()+
geom_smooth(method = "lm")+
facet_wrap(~variable, scales = "free_y")

using ggplot2 in R (geom_rect) to visualise multiple positions along stacked bars of different lengths

Imagine I have 4 samples of different sizes, and within each sample I have sequential positions from m to n.
I'd like to visualise the length of each sample with a coloured bar, and place lines indicating the positions within a sample, like this:
This is what I have so far, however I don’t want the positions to be stored in separate data frames.
library("ggplot2")
# data for coloured bars (samples)
dat=data.frame(x1=c(1,1,1,1), x2=c(200,100,270,500), y1=c(1.1,1.3,1.5,1.7), y2=c(1.2,1.4,1.6,1.8), samp=c('1','2','3','4'))
# data for each position within each sample
pos1=data.frame(x1=c(100,50,24,100), x2=c(101,51,25,101), y1=c(1.1,1.3,1.5,1.7), y2=c(1.2,1.4,1.6,1.8), samp=c('1','2','3','4'))
pos2=data.frame(x1=c(110,65,120,405), x2=c(111,66,121,406), y1=c(1.1,1.3,1.5,1.7), y2=c(1.2,1.4,1.6,1.8), samp=c('1','2','3','4'))
pos3=data.frame(x1=c(190,70,240,442), x2=c(191,71,241,443), y1=c(1.1,1.3,1.5,1.7), y2=c(1.2,1.4,1.6,1.8), samp=c('1','2','3','4'))
# plot each sample above the next
ggplot() +
scale_x_continuous(name="x") +
scale_y_continuous(name="y") +
geom_rect(data=dat, mapping=aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2, fill=samp), color="black", alpha=0.5) +
geom_text(data=dat, aes(x=x1, y=y1, label=samp), size=4) +
geom_rect(data=pos1, mapping=aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), color="black", alpha=0.5) +
geom_rect(data=pos2, mapping=aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), color="black", alpha=0.5) +
geom_rect(data=pos3, mapping=aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), color="black", alpha=0.5)
Can anyone help me to plot this with pos1, pos2, and pos3 combined into a single data frame? I'm also open to suggestions for better ways of doing this!
This is a very simplified version of the data. I have around 20 samples in total, and hundreds of positions per sample.
Any help would be much appreciated!
Cheers : )
EDIT #1:
My raw data looks something like this:
positions=data.frame(sample=c(1,1,1,2,2,2,3,3,3,4,4,4),position=c(100,110,190,50,65,70,24,120,240,100,405,442))
samples=data.frame(sample=c(1,2,3,4), length=c(200,100,270,500))
Update:
I looked at the data again and I think this is more in line with what you are asking for:
dat2 <- dat %>%
mutate(x2 = 0, obs = 0) %>%
bind_rows(pos1 %>% mutate(obs = 1)) %>%
bind_rows(pos2 %>% mutate(obs = 2)) %>%
bind_rows(pos3 %>% mutate(obs = 3)) %>%
bind_rows(dat %>% mutate(obs = 4)) %>%
group_by(samp) %>%
mutate(x = x2 - lag(x2))
ggplot(dat2, aes(x=samp)) +
geom_col(aes(y=x, fill=obs), color="black", alpha=0.5) +
coord_flip() +
scale_fill_gradient(low="steelblue", high="steelblue") +
theme(legend.position = "none")
Original Answer:
I'm not sure I'm reading your data correctly, but here is an attempt:
dat2 <- dat %>%
mutate(obs = 0) %>%
bind_rows(pos1 %>% mutate(obs = 1)) %>%
bind_rows(pos2 %>% mutate(obs = 2)) %>%
bind_rows(pos3 %>% mutate(obs = 3))
ggplot(dat2, aes(x=samp)) +
geom_col(aes(y=x2, fill=obs), color="black", alpha=0.5) +
coord_flip() +
scale_fill_gradient(low="steelblue", high="steelblue") +
theme(legend.position = "none")

Resources