Reputation: 377
I am working with strings that end with a number and would like to put the strings in numerical order for the figure legend.
# Example dataframe
d <- data.frame(
SampleID = sprintf("sample_%s", rep(10:39)),
Variable = 1:30,
Group = append(rep("group_1", each = 15), rep("group_2", each = 15)),
Group1 = runif(30, min=0, max=100),
Group2 = runif(30, min=0, max=100)
)
# Character level I add to give each animal unique shape
d$Animals <- sprintf("Animal_%s",rep(c(1:10), each = 3))
library(ggplot2)
# Plot
ggplot(d, aes(Group1, Group2, color=Group, shape=Animals)) +
xlab(paste0("Value 1")) +
ylab(paste0("Value 2")) +
coord_fixed() +
geom_point() +
scale_shape_manual(values=c(0:10))
Upvotes: 0
Views: 177
Reputation: 2311
The accepted solution is not viable if the number of factors is too large as it requires manually typing the factor levels in the correct order. The other solution proposed (using unique(d$Animals)
to get the levels in the correct order) also may fail if the original data is incorrectly ordered. In case someone needs a more general solution (this is a very common problem) you can use
d$Animals <- factor(sprintf("Animal_%s",rep(c(1:10), each = 3)))
d$Animals <- reorder(d$Animals,
as.numeric(gsub("^[^_]*_(\\d+).*", "\\1", d$Animals)))
This will properly reorder the levels according to the first number found in the string regardless of being 10 or 1000 levels and the order they appear in your dataset.
Upvotes: 1
Reputation: 377
Thank you @Susan Switzer, I'll accept this answer, however I made a slight change to your original solution.
d <- data.frame(
SampleID = sprintf("sample_%s", rep(10:39)),
Variable = 1:30,
Group = append(rep("group_1", each = 15), rep("group_2", each = 15)),
Group1 = runif(30, min=0, max=100),
Group2 = runif(30, min=0, max=100)
)
d$Animals <- sprintf("Animal_%s",rep(c(1:10), each = 3))
library(dplyr)
d <- d %>%
mutate(Animals = factor(Animals,
levels = unique(d$Animals),
ordered = T))
library(ggplot2)
ggplot(d, aes(Group1, Group2, color=Group, shape=Animals)) +
xlab(paste0("Value 1")) +
ylab(paste0("Value 2")) +
coord_fixed() +
geom_point() +
scale_shape_manual(values=c(0:10))
Upvotes: 0
Reputation: 1922
You can make the convert the Animal variable into an ordered and leveled factor
# Example dataframe
d <- data.frame(
SampleID = sprintf("sample_%s", rep(10:39)),
Variable = 1:30,
Group = append(rep("group_1", each = 15), rep("group_2", each = 15)),
Group1 = runif(30, min=0, max=100),
Group2 = runif(30, min=0, max=100)
)
# Character level I add to give each animal unique shape
d$Animals <- sprintf("Animal_%s",rep(c(1:10), each = 3))
d <- d %>%
mutate(Animals = factor(Animals,
levels = c( "Animal_1" , "Animal_2" , "Animal_3" , "Animal_4", "Animal_5" ,
"Animal_6" , "Animal_7", "Animal_8" , "Animal_9" ,"Animal_10"),
ordered = T))
library(ggplot2)
# Plot
ggplot(d, aes(Group1, Group2, color=Group, shape=Animals)) +
xlab(paste0("Value 1")) +
ylab(paste0("Value 2")) +
coord_fixed() +
geom_point() +
scale_shape_manual(values=c(0:10))
Upvotes: 1