How to Conditionally Highlight Points in Ggplot2 Facet Plots - Mapping Color to Column

How to conditionally highlight points in ggplot2 facet plots - mapping color to column

You should put color=ifelse(y<0, 'red', 'black') inside the aes(), so color will be set according to y values in each facet independently. If color is set outside the aes() as vector then the same vector (with the same length) is used in both facets and then you get error because length of color vector is larger as number of data points.

Then you should add scale_color_identity() to ensure that color names are interpreted directly.

ggplot(df) + geom_point(aes(x, y, color=ifelse(y<0, 'red', 'black'))) + 
facet_grid(case ~. ,)+scale_color_identity()

Sample Image

How to highlight points in a facet grid with ggplot?

You could add a column to mark the maximum or minimum value in each facet. The code below adds a column to mark the maximum value in facets where a linear regression fit has a positive slope and the minimum value when the slope is negative. This added column is then mapped to a colour aesthetic to set the point colors. (You can also make the highlighted points larger and/or use a different point marker for them by mapping the new column to, respectively, size and shape aesthetics.)

library(dplyr)

df = df %>%
group_by(variable) %>% # Group by the faceting variable
mutate(highlight = coef(lm(value ~ n))[2], # Get slope for each facet
highlight = ifelse(highlight > 0, # Mark max or min value, depending on slope
ifelse(value==max(value),"Y","N"),
ifelse(value==min(value),"Y","N")))

ggplot(df) +
geom_point(aes(x = n, y = value, colour=highlight), size=2, show.legend=FALSE) +
facet_grid(variable ~ ., scale="free_y") +
scale_colour_manual(values=c("black","red")) +
theme_bw()

Sample Image

You can do this without permanently adding the new column to your data frame by piping the data frame directly to ggplot instead of saving the updated data frame first:

df %>% 
group_by(variable) %>%
mutate(highlight = coef(lm(value ~ n))[2],
highlight = ifelse(highlight > 0,
ifelse(value==max(value),"Y","N"),
ifelse(value==min(value),"Y","N"))) %>%
ggplot() +
geom_point(aes(x=n, y=value, colour=highlight), size=2, show.legend=FALSE) +
facet_grid(variable ~ ., scale="free_y") +
scale_colour_manual(values=c("black","red")) +
theme_bw()

How do you map dynamic colors in ggplot using a highlighter column?

From the documentation in help(scale_fill_manual),

Values:
a set of aesthetic values to map data values to. The values will be matched in order (usually alphabetical) with the limits of the scale, or with breaks if provided. If this is a named vector, then the values will be matched based on the names instead. Data values that don't match will be given na.value.

We can use this to change the code slightly and make it work as expected

cols <- p_test$data$car_color
names(cols) <- p_test$data$car
p_test + scale_fill_manual(values = cols)

Sample Image

Alternatively we could use breaks

breaks: One of:

NULL for no breaks

waiver() for the default breaks (the scale limits)

A character vector of breaks

A function that takes the limits as input and returns breaks as output

eg. we could also do

p_test + scale_fill_manual(values = p_test$data$car_color, breaks = p_test$data$car)

Similar methods can be used together with existing aestethics within the aes object.

R plots with equal color mapping

The issue with your color pattern is that your vales are not sorted in the same order for each plot. On the right plot, hclust will order each id in function of their distance and on the left plot they are sorted by their label id.

To get the same order, you need to attribute the order of hclust to your dataframe. You can find this order in the variable order from your hclust object:

> fit1$order
[1] 5 6 2 3 10 4 1 7 8 9

So, you can now pass this order in your df by doing (after you defined their cluster id):

fit1 <- hclust(d=set1.dist, method = "complete")
df$cluster <- cutree(fit1,k = 3)
df <- df[order(match(df$label, fit1$order)),]

X1 X2 label cluster
5 -0.67846476 0.3034370 5 2
6 0.07798362 0.3578356 6 2
2 0.70596583 0.1961721 2 2
3 0.54889439 0.7668157 3 2
10 -1.70825344 -0.6293518 10 3
4 -0.04557927 -1.6586588 4 1
1 0.33742619 -0.8535244 1 1
7 0.36133829 -0.4064025 7 1
8 0.64431246 -0.3865271 8 1
9 0.59196977 -0.3991278 9 1

Now for plotting the first graph, you need to set cluster as a factor and attribute levels based on this order:

p1 <- df %>% mutate(cluster = factor(cluster, unique(cluster))) %>%
ggplot()+
geom_text(aes(x=X1,y=X2,label=label ,color=cluster))+
theme(legend.position = "none")

Then, the second plot does not change and you will finally get:

Sample Image

Does it answer your question ?

How to assign colors using a variable containing color names in a grouped ggplot?

I think you are looking for scale_color_identity

ggplot(df, aes(wt, mpg)) +
geom_point(aes(color = color)) +
scale_color_identity(guide = "legend") # default is guide = "none"

Sample Image

Here is the respective line plot

ggplot(df, aes(wt, mpg)) +
geom_line(aes(color = color)) +
scale_color_identity(guide = "legend")

Sample Image

How do I get ggplot to read the colors I am feeding it

How about this?

I'm still new to R (and SO) but afaik aes(colour=xxx) doesn't set the actual colour, it determines the scale_color_xxx to apply. You seem to want the colour to change with each Populations2, so change the colour series based on that, if that makes sense.

Sorry, don't have enough rep (yet) to post an image of the output I get as well.

txt <- "Populations alpha   SE  Z   sample  color
Pop1 0.029000 0.003589 8.116 9 red
Pop2 0.031868 0.003498 8.231 9 red
Pop3 0.028969 0.003765 7.942 8 blue
Pop4 0.030651 0.003479 8.792 10 green"

tbl <- read.table(text = txt, header = TRUE)

require(ggplot2)
tbl$Populations2 <- factor(tbl$Populations, as.character(tbl$Populations))

ggplot(tbl, aes(y = Populations2,
x = alpha,
xmin = alpha - SE,
xmax = alpha + SE,
label = Populations2,
colour = Populations2
)) +
geom_point(colour = "black") +
geom_text(hjust = 1.2) +
theme_classic() +
theme(axis.title = element_blank(),
axis.ticks = element_blank(),
axis.text.y = element_blank(),
legend.position = "none") +
geom_errorbarh(height = .1) +
scale_color_manual(values = as.character(tbl$color))

ggplot color is not automatically coloring based on group

@teunbrand was spot on.
Interesting. You may have somehow more or less voluntarily used I(), which lets R interpret an object "as is". See also ?I

Here how to convert back to plain character:

You can do that either temporarily in the call to ggplot itself, or more permanently, by assignment (which I think you want to do).

update
in the comments, user teunbrand pointed to the S3 Method scale_type.AsIs, which is why using an "asIs" object works just like using scale...identity

## this is to reproduce your data structure
iris2 <- iris
iris2$Species <- I(as.character(iris2$Species))

library(ggplot2)
ggplot(iris2, aes(x=Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point()
#> Error: Unknown colour name: setosa

#convert withing ggplot
ggplot(iris2, aes(x=Sepal.Length, y = Sepal.Width, color = as.character(Species))) +
geom_point()

Sample Image

## convert by assignment
iris2$Species <- as.character(iris2$Species)

ggplot(iris2, aes(x=Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point()

Sample Image

Created on 2020-07-01 by the reprex package (v0.3.0)



Related Topics



Leave a reply



Submit