I have the following code:
p <- ggplot() + coord_fixed() + xlab("") + ylab("")
base_world <- p + geom_polygon(data=world_map, aes(x=long, y=lat, group=group),
colour="green", fill="whitesmoke") +
geom_point(data = as.data.frame(coordinates(busxy)), size = 1,
mapping = aes(x = busxy#coords[,1], y = busxy#coords[,2],
color = busxy$color)) +
labs(title = "Cities\n", color = "States\n") +
scale_color_manual(labels = col2state$s, values = col2state$c)
It prints this:
The problem is the colors on map doesn't correspond with those in legend.
When I delete scale_color_manual(labels = col2state$s, values = col2state$c) from the plot it's all right but 'States' have names of colors from the data.
My question is: How to leave labels names like in the image but also assign proper colors to those labels as in the map?
In col2state$c are 29 color names (like #29A934)
In col2state$s are 29 state labels like in legend.
Data frame busxy contains 144k records with 29 unique values of states.
Data is from:
library(maps)
world_map <- map_data("world")
busxy <- data.frame(x=bus[[1]]$latitude, y=bus[[1]]$longitude, city=bus[[1]]$city, state=bus[[1]]$state)
bus <- llply(as.list(jfile5), function(x) jsonlite::stream_in(file(x), pagesize = 10000))
and jfile5 is the path to json file contains all data.
scale_color_manual can do without the labels parameter. A way to solve this is scale_color_manual(values = my_colors) where my_colors is the mapping of countries to their color, organized in a named character vector, e.g. c(AZ = "blue", NV = "red", ...)
An example:
df <- data.frame(x=1:3, y = 2:4, f = as.factor(1:3))
my_colors <- c('1'= "blue", '2' = "red", '3' = "yellow")
ggplot(df) + geom_point(aes(x = x, y = y, color = f)) + scale_color_manual(values = my_colors)
Instead of calling the columns, save vectors of the unique values for color and for state labels. Ensure the vectors are ordered to match.
vec_c <- unique(col2state$c)
vec_s <- unique(col2state$s) #may need to re-order, or opt to manually create vector
scale_color_manual(labels = vec_c, values = vec_s)
Related
I have a colour data frame that I join with my input data to match the colours to categories. The issue is that when using fill=mycolour the legend displays the colour names and not the names of my categories.
I would like fill to be name_assigned while still matching the colours in mycolors.
df %>%
dplyr::left_join(colors.variable, by="name_assigned") %>%
ggplot(aes(reorder(chr,chr,function(x)-length(x)),y=name_assigned, fill=mycolors)) +
geom_bar(aes(y = (..count..))) +
scale_fill_identity()
You don't need the join, from the colors data set create a named colors vector and use it in scale_fill_manual.
Also, you seem to have swapped x and y coordinates.
library(ggplot2)
set.seed(2022)
df <- data.frame(
chr = rbinom(1e3, 1, 0.5),
name_assigned = sample(letters[1:3], 1e3, TRUE)
)
colors.variable <- data.frame(
name_assigned = letters[1:3],
mycolors = c("pink", "purple", "seagreen")
)
mycolors <- with(colors.variable, setNames(mycolors, name_assigned))
ggplot(df, aes(name_assigned, fill = name_assigned)) +
geom_bar() +
scale_fill_manual(values = mycolors)
I need to make 5 plots of bacteria species. Each plot has a different number of species present in a range of 30-90. I want each bacteria to always have the same color in all plots, therefore I need to set an assigned color to each name.
I tried to use scale_colour_manual to create a color set but, the environment created has only 16 colors. How can I increase the number of colors present in the environment created?
the code I am using can be replicated as follow:
colour_genus <- stringi::stri_rand_strings(90, 5) #to be random names
nb.cols = nrow(colour_genus) #to set the length of my string
MyPalette = colorRampPalette(brewer.pal(12,"Set1"))(nb.cols) # the palette of choice
colGenus <- scale_color_manual(name = colour_genus, values = MyPalette)
The output formed contains only 16 values, so when I try to apply it to a figure with 90 factors, it complains I have only 16 values
abundance <- runif(90, min = 10, max = 100)
my_data <- data.frame(colour_genus, abundance)
p <- ggplot(my_data, aes(x = colour_genus, y= abundance)) +
geom_bar(aes(color = colour_genus, fill = colour_genus), stat = "identity", position = "stack") +
labs(x = "", y = "Relative Abundance\n") +
theme(panel.background = element_blank())
p + theme(legend.text= element_text(size=7, face="bold"), axis.text.x = element_text(angle = 90)) + guides(fill=guide_legend(ncol=2)) + scale_fill_manual(values=colGenus)
The following error shows:
Error: Insufficient values in manual scale. 90 needed but only 16 provided.
Thank you very much for your help.
When you know all your 90 bacci names in front of plotting, you can try.
set.seed(123)
colour_genus <- sort(stringi::stri_rand_strings(90, 5))#to be random names. I sorted the vector to illustrate the output better (optional).
MyPalette <- sample(colors(), length(colour_genus))
# named vector for scale_fill
names(MyPalette) <- colour_genus
# data
abundance <- runif(90, min = 10, max = 100)
my_data <- data.frame(colour_genus, abundance)
# two sets to show results
set1 <- my_data[20:30,]
set2 <- my_data[25:35,]
ggplot(set1, aes(x = colour_genus, y= abundance)) +
geom_col(aes(fill = colour_genus)) +
scale_fill_manual(values = MyPalette)
ggplot(set2, aes(x = colour_genus, y= abundance)) +
geom_col(aes(fill = colour_genus)) +
scale_fill_manual(values = MyPalette)
I'm trying to create several plots with ggplot2, and I'd like it to assign always the same color to the each factor type.
Here you have a toy example.
mydata <- data.frame(from=rep(c("b","c"), each=15),
to=rep(c("a","b","c"), each=10),
value=c(rep(1:5,5:1),rep(1:5,1:5)) )
I first convert the categories to factors in order to assign always the same value and because it worked on other plots I did.
I want to create two density plots (or similar) from the value grouped by categories in two ways, one using the categories of the "from" column, another one with the categories of the "to" column, using the same legend.
niv <- c("a", "b", "c")
colo <- c("black", "red", "blue")
mydata$from <- factor(mydata$from, levels=niv)
mydata$to <- factor(mydata$to, levels=niv)
And now I generate the plots.
First with grouping by the "from" column.
ggplot(mydata) + stat_density(geom="line",size=0.8,
position = "identity", aes(x=value, color=from)) +
scale_colour_manual(name="Type",labels = niv,
values=colo) + theme_bw()
As you can see it doesn't produce the desired plot because it shows an "a" factor but it doesn't exist on the "from" column.
And now grouping by the "to" column.
ggplot(mydata) + stat_density(geom="line",size=0.8,
position = "identity", aes(x=value, color=to)) +
scale_colour_manual(name="Type",labels = niv,
values=colo) + theme_bw()
It works as expected.
Now I try to produce again the first plot without the labels parameter.
ggplot(mydata) + stat_density(geom="line",size=0.8,
position = "identity", aes(x=value, color=from)) +
scale_colour_manual(name="Type", values=colo) +
theme_bw()
Now it labels properly the categories but the color don't match with the second plot.
How can I do it?
The real problem has more categories and many values.
You could use a named vector in scale_color_manual to map Type explicitly to colors:
color_map <- c("a" = "black", "b" = "red", "c" = "blue")
scale_colour_manual(values=color_map)
From the help(scale_color_manual):
values
a set of aesthetic values to map data values to. If this is a
named vector, then the values will be matched based on the names. If
unnamed, values will be matched in order (usually alphabetical) with
the limits of the scale. Any data values that don't match will be
given na.value.
Here is the full code that, I believe, produces the output that you want:
library(tidyverse)
mydata <- data.frame(
from = rep(c("b", "c"), each = 15),
to = rep(c("a", "b", "c"), each = 10),
value = c(rep(1:5, 5:1), rep(1:5, 1:5))
)
niv <- c("a", "b", "c")
colo <- c("black", "red", "blue")
color_map <- set_names(colo, niv)
mydata$from <- factor(mydata$from, levels = niv)
mydata$to <- factor(mydata$to, levels = niv)
ggplot(mydata) + stat_density(
geom = "line", size = 0.8,
position = "identity", aes(x = value, color = from)
) +
scale_colour_manual(name = "Type", values = color_map) + theme_bw()
ggplot(mydata) + stat_density(
geom = "line", size = 0.8,
position = "identity", aes(x = value, color = to)
) +
scale_colour_manual(
name = "Type",
values = color_map
) + theme_bw()
As from the title suppose this vector and plot:
plot(rnorm(200,5,2),type="l")
This returns this plot
What i would like to know is whether there is a way to make the first half of it to be in blue col="blue" and the rest of it to be in red "col="red".
Similar question BUT in Matlab not R: Here
You could simply use lines for the second half:
dat <- rnorm(200, 5, 2)
plot(1:100, dat[1:100], col = "blue", type = "l", xlim = c(0, 200), ylim = c(min(dat), max(dat)))
lines(101:200, dat[101:200], col = "red")
Not a base R solution, but I think this is how to plot it using ggplot2. It is necessary to prepare a data frame to plot the data.
set.seed(1234)
vec <- rnorm(200,5,2)
dat <- data.frame(Value = vec)
dat$Group <- as.character(rep(c(1, 2), each = 100))
dat$Index <- 1:200
library(ggplot2)
ggplot(dat, aes(x = Index, y = Value)) +
geom_line(aes(color = Group)) +
scale_color_manual(values = c("blue", "red")) +
theme_classic()
We can also use the lattice package with the same data frame.
library(lattice)
xyplot(Value ~ Index, data = dat, type = 'l', groups = Group, col = c("blue", "red"))
Notice that the blue line and red line are disconnected. Not sure if this is important, but if you want to plot a continuous line, here is a workaround in ggplot2. The idea is to subset the data frame for the second half, plot the entire data frame with color as blue, and then plot the second data frame with color as red.
dat2 <- dat[dat$Index %in% 101:200, ]
ggplot(dat, aes(x = Index, y = Value)) +
geom_line(color = "blue") +
geom_line(data = dat2, aes(x = Index, y = Value), color = "red") +
theme_classic()
I am trying to use ggplot() to plot a betadispers object mod1 so that I can better control the colours.
I extracted the centroids from mod1 and I am using geom_point() for plotting the yearly replicates for each dune , geom_seg()to plot the lines for each dune-star, and a second geom_point() statement to plot the centroids.
When I plot this using
scale_colour_manual(values=cols, guide= FALSE)
it only changes the colour of the first geom_points and the geom_seg but not the centroids.
How do I control the colour of each component separately such that the dune points are coloured by cols, the segments are coloured by cols1 and the centroids use cols2?
I'd also like to change the colour of the black outline for each centroid to cols1.
library(vegan)
library(ggplot2)
cols = c("blue","red")
cols1 = c("green","dark orange")
cols2 = c("purple","yellow")
data(dune)
sites = data.frame(year = rep(c(1:5), times= 4), dune = rep(c(1:4),each=5), dune.type = rep(c("A","B"),each=10))
distances <- vegdist(dune, method = "bray")
#create Betadispersion model on betad (effectively a PCoA)
mod1 <- with(sites, betadisper(distances, dune, type = "centroid"))
s = scores(mod1)
# Get points
pnt_sites = as.data.frame(s$sites)
pnt_sites = cbind(pnt_sites, sites)
# Get centroids
pnt_centroids = as.data.frame(s$centroids)
pnt_centroids$dune = rownames(pnt_centroids)
pnt_centroids$dune.type = rep(c("A","B"),each=2)
# Calculate segments
seg = pnt_sites[, c("PCoA1", "PCoA2", "dune")]
tmp = rename(pnt_centroids, c("PCoA1" = "PCoA1_ctr", "PCoA2" = "PCoA2_ctr"))
seg = join(seg, tmp, "dune")
# Plot
ggplot() +
geom_point(
data = pnt_sites,
aes(x = PCoA1, y = PCoA2, colour = dune.type, shape = dune.type),
size = 2
) +
geom_segment(
data = seg,
aes(x = PCoA1, y = PCoA2, xend = PCoA1_ctr, yend = PCoA2_ctr, colour =
dune.type)
) +
geom_point(
data = pnt_centroids,
aes(x = PCoA1, y = PCoA2, fill = dune.type),
size = 3, shape = 21
) +
scale_colour_manual(values=cols, guide= FALSE) +
coord_equal() +
theme_bw()
You can only specify scale_colour_manual() once per plot, not multiple times for each geom_point call, so you need to combine your centroids and sites into one dataframe (adding variables for centroid/site, and centroid A/centroid B/site A/site B), then plot as a single geom_point() layer
#combine centroids and points into one dataframe
pnt_centroids$year = NA
pnt_centroids$data.type = "centroid"
pnt_sites$data.type = "site"
sites_centroids <- rbind(pnt_centroids, pnt_sites)
sites_centroids$type <- paste(sites_centroids$data.type, sites_centroids$dune.type)
When you define vectors of colors to use for scale_fill_manual and scale_colour_manual, each will have 6 levels, to match the number of variables you have (4 point types plus 2 segment types). Your site points and segments do not have a fill attribute, so fill will be ignored when plotting those points and segments, but you still need to define 6 colors in scale_fill_manual so that your filled points for centroids plot properly.
#change the cols vector definitions at the beginning of code to this
cols.fill <- c("purple", "yellow", "purple", "yellow", "purple", "yellow")
cols.colour <- c("green", "dark orange", "green", "dark orange", "blue", "red")
Specify the new colour, fill, and shape scales in the plot code like this:
# Plot
ggplot() +
geom_segment( #segment must go before point so points are in front of lines
data = seg,
aes(x = PCoA1, y = PCoA2, xend = PCoA1_ctr, yend = PCoA2_ctr, colour = dune.type)) +
geom_point(
data = sites_centroids,
aes(x = PCoA1, y = PCoA2, colour = type, fill = type, shape = type), size = 2) +
scale_colour_manual(values = cols.colour) +
scale_fill_manual(values = cols.fill, guide = FALSE) +
scale_shape_manual(values = c(21, 21, 16, 17)) +
coord_equal() +
theme_bw()
Here is the result. The legend gets a bit busy, it may be better to delete it and use text annotation to label the dune types.