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)
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:
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)
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")
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")