Facet wrap radar plot with three apexes in R - r

I have created the following plot which gives the shape of the plot I desire. But when I facet wrap it, the shapes no longer remain triangular and become almost cellular. How can I keep the triangular shape after faceting?
Sample data:
lvls <- c("a","b","c","d","e","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15")
df <- data.frame(Product = factor(rep(lvls, 3)),
variable = c(rep("Ingredients", 20),
rep("Defence", 20),
rep("Benefit", 20)),
value = rnorm(60, mean = 5))
Now when I use this code, I get the shapes I desire.
ggplot(df,
aes(x = variable,
y = value,
color = Product,
group = Product)) +
geom_polygon(fill = NA) +
coord_polar()
However, the products are all on top of one another so ideally I would like to facet wrap.
ggplot(df,
aes(x = variable,
y = value,
color = Product,
group = Product)) +
geom_polygon(fill = NA) +
coord_polar() +
facet_wrap(~Product)
But when I facet wrap, the shapes become oddly cellular and not triangular (straight lines from point to point). Any ideas on how to alter this output?
Thanks.

Related

ggplot: Using factors to determine colour, shape and fill (issue with fill/color)

I have the following:
set.seed(100)
df <- data.frame(
lng = runif(n=20, min=5, max=10),
lat = runif(n=20, min=40, max=50),
year = rep(c("2001","2002","2003","2004"), each=5),
season = sample(c("spring", "autumn"), 10, replace = T),
info = sample(c("yes","no"), 10, replace = T)
)
Which can be plotted by:
ggplot() +
geom_point(data=df,
aes(x = lng,
y = lat,
color = year,
shape = season),
size=3)
To produce:
Great. But I want a red outline on the shapes were info == "yes".
The desired output would be:
Not made using actual data, just for demonstrative purpose. Made in powerpoint.
Admittedly it is similar to this question here, but not quite.
I am happy to split the df using a filter if easier then two + geom_points()
Many thanks
Jim
Below is a quick solution (not the best), which is to use another scale, and below I use size as the scale, then use guides() to manually specify the shape to appear in the legend. you need to plot the bigger red shapes first and then plot over so that it looks like an outline:
ggplot() +
geom_point(data=subset(df,info=="yes"),
aes(x=lng,y=lat,shape = season,size=info),col="red") +
scale_size_manual(values=3.6)+
geom_point(data=df,
aes(x = lng,
y = lat,
color = year,
shape = season),
size=3)+
guides(size = guide_legend(override.aes = list(shape = 1)))
You can change the legend for the shape by playing around with options in the guide()

plotting stacked points using ggplot

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)

Adding points, symbols, and legends to ggplot

I have created a plot using ggplot (with DF1 dataset below). I would like two additions to this plot:
to add symbol based on DF.SYMBOL dataset (on specified times for two IDs: different shape and color by event).
to add a vertical line within the bar with CONC as legend based on DF.LINE dataset
I would appreciate your suggestion!
ID<-rep(c(1,2),each=6)
START <- c(0, 42,57,300,520,710, 0,31,56,85,120,300)
END <- c(42,57,300,520,710,711,31,56,85,120,300,301)
TYPE <- c("S","NR","R","NR","R","R","S","R","NR","R","NR","NR")
DF1 <-data.frame(ID,START,END,TYPE)
DF1
# converting ID from numeric to factor
DF1 %<>%
dplyr::mutate(ID = factor(ID))
ggplot(DF1,aes(y=ID,yend=ID,x=START,xend=END,color=TYPE))+
geom_segment(aes(y=ID,yend=ID,x=START,xend=END),size=6,lineend= "butt")
DF.SYMBOL dataset to add points and symbols to the plot
ID<-rep(c(1,2),each=2)
EVENT <- rep(c("TBR","PBR"))
TIME <- c(90, 220,120,200)
DF.SYMBOL<-data.frame(ID,EVENT,TIME)
DF.LINE dataset to add a vertical line in bar with CONC in legend above the vertical line for each ID
ID <- c(1,2)
TIME <- c(400, 265)
CONC <- c(23,97)
DF.LINE<-data.frame(ID,TIME, CONC)
Here's the desired plot (edited on powerpoint): symbols based on DF.SYMBOL dataset and black line with value based on DF.LINE dataset.
This should do it. I used geom_errorbarh for the vertical line - I don't know a better way to get a vertical line across a horizontal bar on a discrete scale. For better control of the thickness you might consider changing the geom_segment to a geom_rect.
DF.SYMBOL$ID = factor(DF.SYMBOL$ID)
DF.LINE$ID = factor(DF.LINE$ID)
ggplot(DF1,aes(y=ID))+
geom_segment(aes(yend=ID, x=START, xend=END, color = TYPE),size=6,lineend= "butt") +
geom_point(data = DF.SYMBOL, aes(x = TIME, fill = EVENT, shape = EVENT), size = ) +
scale_shape_manual(values = c(21, 24)) +
scale_fill_manual(values = c("red", "yellow")) +
geom_errorbarh(data = DF.LINE, aes(xmin = TIME, xmax = TIME), height = 0.1) +
geom_text(data = DF.LINE, aes(x = TIME, label = CONC), vjust = -1.5)

Plot legend for multiple histograms plotted on top of each other ggplot

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))

ggplot2: how to add sample numbers to density plot?

I am trying to generate a (grouped) density plot labelled with sample sizes.
Sample data:
set.seed(100)
df <- data.frame(ab.class = c(rep("A", 200), rep("B", 200)),
val = c(rnorm(200, 0, 1), rnorm(200, 1, 1)))
The unlabelled density plot is generated and looks as follows:
ggplot(df, aes(x = val, group = ab.class)) +
geom_density(aes(fill = ab.class), alpha = 0.4)
What I want to do is add text labels somewhere near the peak of each density, showing the number of samples in each group. However, I cannot find the right combination of options to summarise the data in this way.
I tried to adapt the code suggested in this answer to a similar question on boxplots: https://stackoverflow.com/a/15720769/1836013
n_fun <- function(x){
return(data.frame(y = max(x), label = paste0("n = ",length(x))))
}
ggplot(df, aes(x = val, group = ab.class)) +
geom_density(aes(fill = ab.class), alpha = 0.4) +
stat_summary(geom = "text", fun.data = n_fun)
However, this fails with Error: stat_summary requires the following missing aesthetics: y.
I also tried adding y = ..density.. within aes() for each of the geom_density() and stat_summary() layers, and in the ggplot() object itself... none of which solved the problem.
I know this could be achieved by manually adding labels for each group, but I was hoping for a solution that generalises, and e.g. allows the label colour to be set via aes() to match the densities.
Where am I going wrong?
The y in the return of fun.data is not the aes. stat_summary complains that he cannot find y, which should be specificed in global settings at ggplot(df, aes(x = val, group = ab.class, y = or stat_summary(aes(y = if global setting of y is not available. The fun.data compute where to display point/text/... at each x based on y given in the data through aes. (I am not sure whether I have made this clear. Not a native English speaker).
Even if you have specified y through aes, you won't get desired results because stat_summary compute a y at each x.
However, you can add text to desired positions by geom_text or annotate:
# save the plot as p
p <- ggplot(df, aes(x = val, group = ab.class)) +
geom_density(aes(fill = ab.class), alpha = 0.4)
# build the data displayed on the plot.
p.data <- ggplot_build(p)$data[[1]]
# Note that column 'scaled' is used for plotting
# so we extract the max density row for each group
p.text <- lapply(split(p.data, f = p.data$group), function(df){
df[which.max(df$scaled), ]
})
p.text <- do.call(rbind, p.text) # we can also get p.text with dplyr.
# now add the text layer to the plot
p + annotate('text', x = p.text$x, y = p.text$y,
label = sprintf('n = %d', p.text$n), vjust = 0)

Resources