Add select points to colored bspline - r

Continuing on from my previous bspline question
If this is my curve:
data <- tibble (
x = c(10, 15, 17, 17, 20, 22, 22, 23, 25, 25, 27, 29),
y = c(5, 7, 4, 4, 0, 5, 5, 6, 5, 5, 4, 5.5),
g = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "D","D","D"),
pt = c(0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1)
)
ggplot(data) +
stat_bspline2(aes(x=x, y=y, color = ..group.., group = g), size = 4, n = 300, geom = "bspline0") +
scale_color_gradientn(colours = c("red", "pink", "green", "white"), guide = F)
How do I add dots to selected points on the curve?
Here's how not to do it:
ggplot(data) +
stat_bspline2(aes(x=x, y=y, color = ..group.., group = g), size = 4, n = 300, geom = "bspline0") +
scale_color_gradientn(colours = c("red", "pink", "green", "white"), guide = F) +
stat_bspline2(data = pt, aes(x = x, y = x, color = ..group.., group = pt), n = 12, geom = "point", size = 9)
)

It isn't perfect, but it works. Add some columns with the positions of the points you want (I'm assuming that if pt = 1, you want the point plotted)
data <- data %>%
mutate(pt_x = ifelse(pt == 1, x, NA),
pt_y = ifelse(pt == 1, y, NA))
ggplot(data) +
stat_bspline2(aes(x=x, y=y, color = ..group.., group = g), size = 4, n = 300, geom = "bspline0") +
scale_color_gradientn(colours = c("red", "pink", "green", "white"), guide = F) +
geom_point(aes(pt_x, pt_y))

Related

Separate legend by facet for geom_segment and geom_point

I am interested in creating a figure akin to the below, which has a separate legend entry for each of four components: two geom_segment and two geom_point, which are grouped according to some facet (corresponding to the color).
Here is a sample dataset, and some initial code.
x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
y <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
z <- c(3, 6, 9, 12, 15, 18, 21, 24, 27, 30)
s <- c(5, 5, 5, 5, 5, 5, 5, 5, 5, 5)
t <- c(10, 10, 10, 10, 10, 10, 10, 10, 10, 10)
n <- c("A", "A", "A", "A", "A", "A", "A", "A", "A", "A",
"B", "B", "B", "B", "B", "B", "B", "B", "B", "B")
df <- cbind(rbind(data.frame(x = x, y = y, s = s), data.frame(x = x, y = z, s = t)), n)
ggplot(data = df, mapping = aes(x = x, y = y, color = n)) +
geom_point() +
scale_color_manual(values = c("blue", "gray64")) +
geom_segment(mapping = aes(x = 0, xend = 10, y = 10, yend = 10), color = "blue", inherit.aes = FALSE) +
geom_segment(mapping = aes(x = 0, xend = 10, y = 20, yend = 20), color = "gray64", inherit.aes = FALSE)
Give this a shot:
library(ggplot2)
ggplot() +
geom_point(data = dplyr::filter(df, n == "A"), mapping = aes(x = x, y = y, shape = "Label A.1"), color = "gray") +
geom_point(data = dplyr::filter(df, n == "B"), mapping = aes(x = x, y = y, shape = "Label B.1"), color = "blue") +
geom_line(data = dplyr::filter(df, n == "A"), mapping = aes(x = x, y = s, color = "Label A.2")) +
geom_line(data = dplyr::filter(df, n == "B"), mapping = aes(x = x, y = s, color = "Label B.2")) +
scale_shape_manual(name = NULL, values = c(19, 19)) +
scale_color_manual(name = NULL, values = c("Label A.2" = "gray", "Label B.2" = "blue")) +
guides(shape = guide_legend(override.aes = list(color = c("Label A.1" = "gray", "Label B.1" = "blue"))))
ggplot2 doesn't seem to like separating legends (I suppose it does make the plot more complicated). In this solution, we add each layer separately, controlling the legend using shape (which we later set to 19, the default filled-in circle) and color aesthetics. In the last line, we make sure the colors of the shape layer are correct (try the code without the last line to see what it does!).
I also don't think "facet" is used correctly in your question. Generally, facets are like subplots.

How to make the rows within a facet appear according to the level of another vector?

The goal is to get the "name"s with increasing "startTime"s displayed from top to bottom, within each facet. Facet A is wrong; Facet B is correct.
library(tidyverse)
my_tribble <- tribble(
~name, ~order.x, ~startTime, ~endTime, ~order.y, ~endTime.y, ~diff, ~area,
"unit1", "dump", 0, 1, "wait", 2, 2, "A",
"unit3", "dump", 5, 7, "wait", 9, 4, "A",
"unit4", "dump", 8, 9, "wait", 10, 2, "B",
"unit2", "dump", 17, 20, "wait", 23, 6, "B"
)
ggplot(my_tribble) +
geom_linerange(aes(ymin = startTime, ymax = endTime.y, x = name),position = position_dodge(width = 0.2), size = 2) +
facet_grid(area ~ ., scales = "free_y") +
coord_flip() +
scale_x_reordered() +
scale_y_continuous(expand = c(0,0))
my_tribble$name <- factor(my_tribble$name, levels = my_tribble$name[order(-my_tribble$startTime)])
ggplot(my_tribble) +
geom_linerange(aes(ymin = startTime, ymax = endTime.y, x = name),position = position_dodge(width = 0.2), size = 2) +
facet_grid(area ~ ., scales = "free_y") +
coord_flip() +
scale_y_continuous(expand = c(0,0))

Selective colouring of data points and text in ggplot

I have my data
varechem <-
structure(
list(
`POX-C` = c(
869.153225806452,
841.409274193548,
720.344758064516,
828.798387096774,
904.46370967742,
773.310483870968,
793.487903225806,
874.197580645161,
900.932661290323,
778.354838709677
),
`B-glucosidase` = c(
1.90612612612613,
1.60509009009009,
1.42864864864865,
1.82355855855856,
1.76761261261261,
1.34855855855856,
1.37504504504504,
1.5863963963964,
1.1290990990991,
1.4686036036036
),
Protein = c(
6284.21052631579,
6250.52631578947,
6103.15789473684,
6280,
6275.78947368421,
4368.42105263158,
1240,
6191.57894736842,
5745.26315789474,
6970.52631578947
)
),
row.names = c(
"M.T1.R1.S1.16S.S50",
"M.T1.R1.S2.16S.S62",
"M.T1.R1.S3.16S.S74",
"M.T1.R2.S1.16S.S86",
"M.T1.R2.S2.16S.S3",
"M.T1.R2.S3.16S.S15",
"M.T1.R3.S1.16S.S27",
"M.T1.R3.S2.16S.S39",
"M.T1.R3.S3.16S.S51",
"M.T1.R4.S1.16S.S63"
),
class = "data.frame"
)
varespec <-
structure(
list(
A = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
B = c(1,
1, 1, 1, 1, 1, 1, 1, 1, 1),
C = c(1, 1, 1, 2, 1, 1, 1, 1, 1,
3),
D = c(2, 1, 1, 1, 1, 1, 1, 1, 1, 1),
E = c(1, 1, 1, 1, 1,
3, 1, 1, 1, 1),
F = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
G = c(1,
1, 11, 20, 15, 13, 23, 9, 1, 16),
H = c(2, 1, 1, 4, 1, 1, 1,
1, 1, 1),
I = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
J = c(9, 3, 20,
21, 16, 19, 22, 13, 12, 26)
),
row.names = c(
"M.T1.R1.S1.16S.S50",
"M.T1.R1.S2.16S.S62",
"M.T1.R1.S3.16S.S74",
"M.T1.R2.S1.16S.S86",
"M.T1.R2.S2.16S.S3",
"M.T1.R2.S3.16S.S15",
"M.T1.R3.S1.16S.S27",
"M.T1.R3.S2.16S.S39",
"M.T1.R3.S3.16S.S51",
"M.T1.R4.S1.16S.S63"
),
class = "data.frame"
)
I have my codes:
library(ggplot2); library(vegan)
sol <- cca(varespec, varechem)
scrs<-scores(sol,display=c("sp","wa","lc","bp","cn"))
df_sites <- data.frame(scrs$sites)
df_sites$Sites <- gsub("\\..*", "", rownames(varechem))
df_sites$Sites <- factor(df_sites$Sites)
# rownames(df_sites) <- gsub("[*].*$", "",rownames(df_sites))
colnames(df_sites)<-c("x","y","Sites")
#Draw sites
p<-ggplot()
p<-p+geom_point(data=df_sites,aes(x,y,colour=Sites), shape = "diamond", size = 2)
p <- p + scale_colour_manual(values = c("blue"), guide = FALSE)
p
#Draw biplots
multiplier <- vegan:::ordiArrowMul(scrs$biplot)
df_arrows<- scrs$biplot*multiplier
colnames(df_arrows)<-c("x","y")
df_arrows=as.data.frame(df_arrows)
#adding arrows for chemicals (environment variables)
pa<-p+geom_segment(data=df_arrows, aes(x = 0, y = 0, xend = x, yend = y),
arrow = arrow(length = unit(0.3, "cm")), arrow.fill = "black")
pa
###adjust the position of the labels or shapes
df_arrows <- as.data.frame(df_arrows*1.1)
df_arrows$Chemicals <- factor(rownames(df_arrows))
cp <- pa+geom_point(data= df_arrows, aes(x, y, group= Chemicals, shape = Chemicals), size = 4) + scale_shape_manual(values=1:nlevels(df_arrows$Chemicals)) + coord_equal()
#### # Draw species
df_species<- as.data.frame(scrs$species)
colnames(df_species)<-c("x","y")
significant_taxa <- c("A", "D")
df_species$significant <- ifelse(rownames(df_species) %in% significant_taxa, "Sig", "Not-sig")
df_species$significant <- as.character(df_species$significant)
get.colour <- c("red", "orange")
#relevel factor so "Sig" will appear first in the legend
df_species$significant <- factor(df_species$significant, levels = c("Sig", "Not-sig"))
df_species$coloured <- "black"
df_species$coloured [match(significant_taxa, rownames(df_species))] <- get.colour
df_species$coloured <- as.factor(df_species$coloured)
library(dplyr)
df_species <- df_species %>%
mutate(labels = rownames(df_species))
scp <- cp+geom_point(data=df_species,aes(x=x,y=y, group = significant, size = significant))+
scale_size_manual(values =c(2.5, 0.2))
scp
library(ggrepel)
scp + geom_text_repel(data = subset(df_species, significant == "Sig"),
aes(x = x, y = y, label = labels), angle = 60, size = 3)
I am having problem colouring only A and D text and the corresponding two data points in different colours (say green and red). How can I do this ?
I think your error is about the use of group = significant in the geom_point, it prevents for the definition of color. If you use this code, you will get the right plot:
ggplot() +
geom_point(data=df_sites,aes(x,y), color = "blue", shape = "diamond", size = 2) +
geom_segment(data=df_arrows, aes(x = 0, y = 0, xend = x, yend = y),
arrow = arrow(length = unit(0.3, "cm")), arrow.fill = "black") +
geom_point(data= df_arrows, aes(x, y, group= Chemicals, shape = Chemicals), size = 4) +
scale_shape_manual(values=1:nlevels(df_arrows$Chemicals)) +
coord_equal() +
geom_point(data = df_species, aes(x = x, y = y, color = coloured, size = significant)) +
scale_size_manual(values = c(2.5, 1)) +
geom_text_repel(data = subset(df_species, significant == "Sig"),
aes(x = x, y = y, label = labels, color = coloured), angle = 60, size = 3) +
scale_color_manual(values = c("black","orange","red"), guide = FALSE)

How to colour and insert text for specific data points in geom_point

I have my data
varechem <-
structure(
list(
`POX-C` = c(
869.153225806452,
841.409274193548,
720.344758064516,
828.798387096774,
904.46370967742,
773.310483870968,
793.487903225806,
874.197580645161,
900.932661290323,
778.354838709677
),
`B-glucosidase` = c(
1.90612612612613,
1.60509009009009,
1.42864864864865,
1.82355855855856,
1.76761261261261,
1.34855855855856,
1.37504504504504,
1.5863963963964,
1.1290990990991,
1.4686036036036
),
Protein = c(
6284.21052631579,
6250.52631578947,
6103.15789473684,
6280,
6275.78947368421,
4368.42105263158,
1240,
6191.57894736842,
5745.26315789474,
6970.52631578947
)
),
row.names = c(
"M.T1.R1.S1.16S.S50",
"M.T1.R1.S2.16S.S62",
"M.T1.R1.S3.16S.S74",
"M.T1.R2.S1.16S.S86",
"M.T1.R2.S2.16S.S3",
"M.T1.R2.S3.16S.S15",
"M.T1.R3.S1.16S.S27",
"M.T1.R3.S2.16S.S39",
"M.T1.R3.S3.16S.S51",
"M.T1.R4.S1.16S.S63"
),
class = "data.frame"
)
varespec <-
structure(
list(
A = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
B = c(1,
1, 1, 1, 1, 1, 1, 1, 1, 1),
C = c(1, 1, 1, 2, 1, 1, 1, 1, 1,
3),
D = c(2, 1, 1, 1, 1, 1, 1, 1, 1, 1),
E = c(1, 1, 1, 1, 1,
3, 1, 1, 1, 1),
F = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
G = c(1,
1, 11, 20, 15, 13, 23, 9, 1, 16),
H = c(2, 1, 1, 4, 1, 1, 1,
1, 1, 1),
I = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
J = c(9, 3, 20,
21, 16, 19, 22, 13, 12, 26)
),
row.names = c(
"M.T1.R1.S1.16S.S50",
"M.T1.R1.S2.16S.S62",
"M.T1.R1.S3.16S.S74",
"M.T1.R2.S1.16S.S86",
"M.T1.R2.S2.16S.S3",
"M.T1.R2.S3.16S.S15",
"M.T1.R3.S1.16S.S27",
"M.T1.R3.S2.16S.S39",
"M.T1.R3.S3.16S.S51",
"M.T1.R4.S1.16S.S63"
),
class = "data.frame"
)
I have my codes:
library(vegan); library(ggplot2)
sol <- cca(varespec, varechem)
scrs <- scores(sol, display = c("sp", "wa", "lc", "bp", "cn"))
df_sites <- data.frame(scrs$sites)
df_sites$Sites <- gsub("\\..*", "", rownames(varechem))
df_sites$Sites <- factor(df_sites$Sites)
# rownames(df_sites) <- gsub("[*].*$", "",rownames(df_sites))
colnames(df_sites) <- c("x", "y", "Sites")
#Draw sites
p <- ggplot()
p <-
p + geom_point(
data = df_sites,
aes(x, y, colour = Sites),
shape = "diamond",
size = 2
)
p <- p + scale_colour_manual(values = c("blue"), guide = FALSE)
p
#Draw biplots
multiplier <- vegan:::ordiArrowMul(scrs$biplot)
df_arrows <- scrs$biplot * multiplier
colnames(df_arrows) <- c("x", "y")
df_arrows = as.data.frame(df_arrows)
#adding arrows for chemicals (environment variables)
pa <-
p + geom_segment(
data = df_arrows,
aes(
x = 0,
y = 0,
xend = x,
yend = y
),
arrow = arrow(length = unit(0.3, "cm")),
arrow.fill = "black"
)
pa
###adjust the position of the labels or shapes
df_arrows <- as.data.frame(df_arrows * 1.1)
df_arrows$Chemicals <- factor(rownames(df_arrows))
cp <-
pa + geom_point(data = df_arrows,
aes(x, y, group = Chemicals, shape = Chemicals),
size = 4) + scale_shape_manual(values = 1:nlevels(df_arrows$Chemicals))
#### # Draw species
df_species <- as.data.frame(scrs$species)
colnames(df_species) <- c("x", "y")
significant_taxa <- c("A", "D")
df_species$significant <-
ifelse(rownames(df_species) %in% significant_taxa, "Sig", "Not-sig")
df_species$significant <- as.character(df_species$significant)
get.colour <- c("red", "orange")
# scp <- cp + geom_point(data = df_species, aes(x, y), size = 0.5)
#relevel factor so "Sig" will appear first in the legend
df_species$significant <-
factor(df_species$significant, levels = c("Sig", "Not-sig"))
df_species$coloured <- "black"
df_species$coloured [match(significant_taxa, rownames(df_species))] <-
get.colour
df_species$coloured <- as.factor(df_species$coloured)
This is where I need help. I need to put two colours for siginficant values
(Sig only) from df_species$coloured and get their labels from the dataframe
rownames(df_species) which is A and D in their respective font colours. So I
would like to put two colours and text associated with that A and D. How
can I do this?
scp <- cp + geom_point(data = df_species, aes(x, y, group = significant, size = significant)) +
scale_size_manual(values = c(4.5, 0.2))
scp
I think I have a solution. I added an extra column to df_species to create the labels in the plot.
df_species <- df_species %>%
mutate(labels = rownames(df_species))
The plot: (This part is updated based on the comment of the OP.)
scp <- ggplot() +
geom_point(data = df_species,
aes(x = x,
y = y,
colour = coloured,
size = significant)) +
geom_text(data = subset(df_species, significant == "Sig"),
aes(x = x,
y = y,
label = labels,
colour = coloured),
hjust = 1,
vjust = -1,
show.legend = FALSE) +
scale_colour_manual(values = c("black" = "black", "red" = "red", "orange" = "orange")) +
scale_size_manual(values = c(4.5, 0.2)) +
geom_point(data = df_sites,
aes(x = x,
y = y,
fill = Sites),
size = 2,
pch = 23) + # with this shape you can use fill
scale_fill_manual(values = c("M" = "blue")) +
geom_point(data = df_arrows,
aes(x = x,
y = y,
group = Chemicals,
shape = Chemicals),
size = 4) +
scale_shape_manual(values = 1:nlevels(df_arrows$Chemicals)) +
geom_segment(data = df_arrows,
aes(x = 0,
y = 0,
xend = x,
yend = y),
arrow = arrow(length = unit(0.3, "cm")),
arrow.fill = "black")
scp
It took a bit of playing around, but I hope this is what you where looking for. :-) I added everything together. For me this was a bit easier to get the overview. The position / order of the scale_* functions is important.

Chop up bsplines and color them

I am intrigued by this plot of Albert Cairo.
I can smooth my curve sufficiently with ggforce::bspline
However, now that I don't have a date axis I am unsure as to how to change the color of a spline midway.
Let's assume that the three points represent the years 1990, 1991 and 1992. And someone got elected on July 1, 1990. I would like to change the color of the spline at this point. So the curved line would be red from origin until aprox (12, 5.6) then blue from (12, 5.6) to (17,4)
I am not sure how to accomplish this.
library(ggforce)
library(ggplot2)
data <- tibble (
x = c(10, 15, 17),
y = c(5, 7, 4)
)
ggplot(data) +
stat_bspline2(aes(x = x, y = y), n = 300, geom = "bspline0", color = "red") +
stat_bspline2(aes(x = x, y = y), n = 3, geom = "point", color = "red") +
geom_point(aes(x = x, y = y), color = "grey")
Thinking about what M.A. told me about groups I now have code that can:
Change the color of straight line segments:
# Works for straight lines
ggplot(data, aes(x=x, y=y, colour = g, group = 1)) +
geom_line(size = 3) +
geom_point() +
scale_color_manual(values = c("A" = "red", "B" = "pink", "C" = "green", "D" = "white"))
And the continuous colour of a bspline. But I would like this to be discrete colors only as in the plot above.
# Works with continuous color
ggplot(data, aes(x=x, y=y, colour = g, group = 1)) +
geom_bspline2(size = 4, n = 300) +
scale_color_manual(values = c("A" = "red", "B" = "pink", "C" = "green", "D" = "white"))
Or this error, "Error: Continuous value supplied to discrete scale" with:
ggplot(data) +
stat_bspline2(aes(x = x, y = y, color = ..group.., group = 1), n = 300, geom = "bspline0") +
scale_color_manual(values = c("A" = "red", "B" = "pink", "C" = "green", "D" = "white"))
So I'm wondering how to manually control the color of discrete segments with bspline.
You can do this by grouping:
data <- tibble (
x = c(10, 15, 17, 17, 20, 22),
y = c(5, 7, 4, 4, 0, 5),
g = c("A", "A", "A", "B", "B", "B")
)
ggplot(data) +
stat_bspline2(
aes(x = x, y = y, color = ..group.., group = g),
n = 300, geom = "bspline0") +
scale_colour_gradient(low = "blue", high = "red", guide=FALSE)
Edit:
The error Continuous value supplied to discrete scale is is somewhat confusing here. I don't know if there is an easier way to get what you want but it can be achieved using scale_colour_gradientn(). This function allows to map the group g to a gradient between n colours so you want n to be the number of groups.
For example, consider a larger data set with four groups:
# example data
data <- tibble (
x = c(10, 15, 17, 17, 20, 22, 22, 23, 25, 25, 27, 29),
y = c(5, 7, 4, 4, 0, 5, 5, 6, 5, 5, 4, 5.5),
g = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "D","D","D")
)
You can use a palette like rainbow() and specify the number of colours for the gradient to be 4 since there are four groups A, B, C and D.
# use a colour palette:
ggplot(data) +
stat_bspline2(
aes(x = x, y = y, color = ..group.., group = g),
n = 300, size = 1, geom = "bspline0") +
scale_color_gradientn(colours = rainbow(4),
guide = F
)
For custom colours, you may do the following:
# use custom colors:
ggplot(data, aes(x=x, y=y, color = ..group.., group = g)) +
geom_bspline2(size = 1, n = 300) +
scale_color_gradientn(
colours = c("red", "pink", "green", "white"),
guide = F
)
This uses a gradient between the colours red, pink, green and white. Note that the order of the colours matters as a different order leads to a different gradient and thus a different mapping of the groups.

Resources