I have created the following dataframe in R. The first step is to import the necessary libraries
library(ggplot2)
library(plotly)
library(dplyr)
We create the dataframe here as follows
DF_1<-data.frame("A"= c(1:10))
DF_1$B<-c("D", "C")
DF_1$C<-DF_1$A^2
Next we create a plot as follows
p2<-ggplot(DF_1, aes(x=A, y=C, group=B, fill=B)) +
geom_line(size=.5) + geom_ribbon(data=subset(DF_1),aes(x=A,ymax=C),ymin=0,alpha=0.3) +
scale_fill_manual(name='Legend', values=c("green4", "red"), labels=c("D", "C" ))+theme_bw()
When p2 is rendered, the legend displays correctly. When I nest p2 in ggplotly, the legend changes to two dark lines.
p3<-ggplotly(p2, dynamicTicks = T)
p3= layout(p3, xaxis = list(type = "log"))
Is it possible to retain the legends of p2 in p3. I request someone to take a look
Looks like ggplotly is a more sensible than ggplot2 in how one sets the aesthetics. Simply moving the fill aes from the global setup in ggplot into geom_ribbon gives the correct legend:
library(ggplot2)
library(plotly)
library(dplyr)
DF_1<-data.frame("A"= c(1:10))
DF_1$B<-c("D", "C")
DF_1$C<-DF_1$A^2
ggplot(DF_1, aes(x = A, y = C, group=B)) +
geom_line(size=.5) +
geom_ribbon(aes(x = A, ymin = 0, ymax = C, fill = B), alpha=0.3) +
scale_fill_manual(name='Legend', values=c("green4", "red"), labels=c("D", "C" ))+theme_bw()
ggplotly(dynamicTicks = T) %>%
layout(xaxis = list(type = "log"))
Related
I would like to make a PCA score plot using ggplot2, and then convert the plot into interactive plot using plotly.
What I want to do is to add a frame (not ellipse using stat_ellipse, I know it worked).
My problem is that when I try to use sample name as tooltip in ggplotly, the frame will disappear. I don't know how to fix it.
Below is my code
library(ggplot2)
library(plotly)
library(dplyr)
## Demo data
dat <- iris[1:4]
Group <- iris$Species
## Calculate PCA
df_pca <- prcomp(dat, center = T, scale. = FALSE)
df_pcs <- data.frame(df_pca$x, Group = Group)
percentage <-round(df_pca$sdev^2 / sum(df_pca$sdev^2) * 100, 2)
percentage <-paste(colnames(df_pcs),"(", paste(as.character(percentage), "%", ")", sep = ""))
## Visualization
Sample_Name <- rownames(df_pcs)
p <- ggplot(df_pcs, aes(x = PC1, y = PC2, color = Group, label = Sample_Name)) +
xlab(percentage[1]) +
ylab(percentage[2]) +
geom_point(size = 3)
ggplotly(p, tooltip = "label")
Until here it works! You can see that sample names can be properly shown in the ggplotly plot.
Next I tried to add a frame
## add frame
hull_group <- df_pcs %>%
dplyr::mutate(Sample_Name = Sample_Name) %>%
dplyr::group_by(Group) %>%
dplyr::slice(chull(PC1, PC2))
p2 <- p +
ggplot2::geom_polygon(data = hull_group, aes(fill = Group), alpha = 0.1)
You can see that the static plot still worked! The frame is properly added.
However, when I tried to convert it to plotly interactive plot. The frame disappeared.
ggplotly(p2, tooltip = "label")
Thanks a lot for your help.
It works if you move the data and mapping from the ggplot() call to the geom_point() call:
p2 <- ggplot() +
geom_point(data = df_pcs, mapping = aes(x = PC1, y = PC2, color = Group, label = Sample_Name), size = 3) +
ggplot2::geom_polygon(data = hull_group, aes(x = PC1, y = PC2, fill = Group, group = Group), alpha = 0.2)
ggplotly(p2, tooltip = "label")
You might want to change the order of the geom_point and geom_polygon to make sure that the points are on top of the polygon (this also affects the tooltip location).
I have my an empty panel in my facetted ggplot. I would like to insert my standalone plot into this. Is this possible? See below for example code.
I found a possible solution Here, but can't get it to 'look nice'. To 'look nice' I want the standalone plot to have the same dimensions as one of the facetted plots.
library(ggplot2)
library(plotly)
data("mpg")
first_plot = ggplot(data = mpg, aes(x = trans, y = cty)) +
geom_point(size= 1.3)
facet_plot = ggplot(data = mpg, aes(x = year, y = cty)) +
geom_point(size = 1.3) +
facet_wrap(~manufacturer)
facet_plot # room for one more panel which I want first_plot to go?
# try an merge but makes first plot huge, compared with facetted plots.
subplot(first_plot, facet_plot, which_layout = 2)
Besides the options to manipulate the gtable or using patchwork one approach to achieve your desired result would be via some data wrangling to add the standalone plot as an additional facet. Not sure whether this will work for your real data but at least for mpg you could do:
library(ggplot2)
library(dplyr)
mpg_bind <- list(standalone = mpg, facet = mpg) %>%
bind_rows(.id = "id") %>%
mutate(x = ifelse(id == "standalone", trans, year),
facet = ifelse(id == "standalone", "all", manufacturer),
facet = forcats::fct_relevel(facet, "all", after = 1000))
ggplot(data = mpg_bind, aes(x = x, y = cty)) +
geom_point(size = 1.3) +
facet_wrap(~facet, scales = "free_x")
I have a data frame and I would like to stack the points that have overlaps exactly on top of each other.
here is my example data:
value <- c(1.080251e-04, 1.708859e-01, 1.232473e-05, 4.519876e-03,2.914256e-01, 5.869711e-03, 2.196347e-01,4.124873e-01, 5.914052e-03, 2.305623e-03, 1.439013e-01, 5.407597e-03, 7.530298e-02, 7.746897e-03)
names = letters[1:7]
data <- data.frame(names = rep(names,), group = group, value = value, stringsAsFactors = T)
group <- c(rep("AA", 7) , rep("BB", 7))
I am using the following command:
p <- ggplot(data, aes(x = names, y = "", color = group)) +
geom_point(aes(size = -log(value)), position = "stack")
plot(p)
But the stacked circle outlines out of the grid. I want it close or exactly next to the bottom circle. do you have any idea how I can fix the issue?
Thanks,
The y-axis has no numeric value, so use the group instead. And we don't need the color legend now since the group labels are shown on the y-axis.
ggplot(data, aes(x = names, y = group, color = group)) +
geom_point(aes(size = -log(value))) +
guides(color=FALSE)
I map the same variable (color) to color in two different geoms. I want them either to appear in separate legends (DHJ and EFI) or preferably just skip the second legend (for E, F, and I) altogether. Currently, R mixes the two together and gives me a legend that lists DEFHIJ in alphabetical order all mixed together.
Basically, I want to graph today's points onto some smoothed lines that use a standard dataset. I don't want there to be a legend for the smoothed lines - we are all familiar with them and they are standard on all our graphs. I just want a legend for the points only.
I've tried show.legend = FALSE as suggested elsewhere, but that doesn't seem to have an effect. guides(color = FALSE) removes the entire legend.
Reprex:
library(tidyverse)
set1 <- diamonds %>%
filter(color %in% c("D", "H", "J"))
set2 <- diamonds %>%
filter(color %in% c("E", "F", "I"))
ggplot() +
geom_point(data = set1,
aes(x = x, y = y, color = color)) +
geom_smooth(data = set2,
show.legend = FALSE,
aes(x = x, y = y, color = color))
Here is the graph that is produced. It has all 6 letters in the legend, instead of only DHJ.
If you want the legend to show only the colors from one dataset you can do so by setting the breaks in scale_color_discrete() to those values.
... +
scale_color_discrete(breaks = unique(set1$color) )
If you aren't using the colors of the lines, since this is standard background info, you could add the lines by using group ingeom_smooth() instead of color. (Also see linetype if you wanted to be able to tell the lines apart.)
ggplot() +
geom_point(data = set1,
aes(x = x, y = y, color = color)) +
geom_smooth(data = set2,
aes(x = x, y = y, group = color))
I've made this multiple histogram plot in ggplot and now I want to add a legend for both the light purple part and the dark purple part. I know the conventional way is to to it with aes, but I can't seem to figure out how I integrate this feature as one into my multiple histogram plot.
I don't shy manual labour, but more sophisticated solutions are preferred. Anyone help me out?
#dataframe
set.seed(20)
df <- data.frame(expl = rbinom(n=100, size = 1, prob=0.08),
resp = sample(50:100, size = 100, replace = T))
#graph
graph <- ggplot(data = df, aes(x = resp))
graph +
geom_histogram(fill = "#BEBADA", alpha = 0.5, bins = 10) +
geom_histogram(data = subset(df, expl == '1'), fill = "#BEBADA", bins = 10)
Your data is already in the long format that is well suited for ggplot; you just need to map expl to alpha. In general, if you find yourself making multiples of the same geom, you probably want to rethink either the shape of your data or your approach for feeding it into geoms.
library(tidyverse)
set.seed(20)
df <- data.frame(expl = rbinom(n=100, size = 1, prob=0.08),
resp = sample(50:100, size = 100, replace = T))
To map expl onto alpha, make it a factor, and then assign that to alpha inside your aes. Then you can set the alpha scale to values of 0.5 and 1.
ggplot(df, aes(x = resp, alpha = as.factor(expl))) +
geom_histogram(fill = "#bebada", bins = 10) +
scale_alpha_manual(values = c(0.5, 1))
However, differentiating by alpha is a little awkward. You could instead map to fill and use light and dark purples:
ggplot(df, aes(x = resp, fill = as.factor(expl))) +
geom_histogram(bins = 10) +
scale_fill_manual(values = c("0" = "mediumpurple1", "1" = "mediumpurple4"))
Note also that you can adjust the position of the histogram bars if you need to, by assigning geom_histogram(position = ...), where you could fill in with something such as "dodge" if that's what you'd like.
If you want a legend on the alpha value, the idea is to include it as an aesthetic rather than as a direct argument as you tried. In order to do this, a simple solution is to enrich the data frame used by ggplot:
df2 <- rbind(
cbind(df, filter="all lines"),
cbind(subset(df, expl == '1'), filter="expl==1")
)
df2 corresponds to df after appending the lines from your subset of interest (with a field filter telling from which copy each record comes)
Then, this solves your problem
ggplot(df2, aes(resp, alpha=filter)) +
geom_histogram(fill="#BEBADA", bins=10, position="identity") +
scale_alpha_discrete(range=c(.5,1))