Stacked bar plot in R with the positive and negative values - r

I would like to plot a stacked bar plot in R and my data looks as such:
This table is the values against date and as it can be seen, there are repetitive dates with different sides. I would like to plot a bar plot using this data.
combined = rbind(x,y)
combined = combined[order(combined$Group.1),]
barplot(combined$x,main=paste("x vs y Breakdown",Sys.time()),names.arg = combined$Group.1,horiz = TRUE,las=2,xlim=c(-30,30),col = 'blue',beside = True)
Want a stacked plot where I can see the values against dates. How do change my code?

You can easily create this figure with ggplot2.
Here a piece of code for you using a data frame similar to what you have:
library(ggplot2)
my_data <- data.frame(
date = factor(c(1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8)),
x = c(-2, 14, -8, -13, 3, -4, 9, 8, 3, -4, 8, -1)
)
g <- ggplot(my_data, aes(x = date, y = x)) +
geom_bar(
stat = "identity", position = position_stack(),
color = "white", fill = "lightblue"
) +
coord_flip()
This is the output:
Obviously, the official documentation is a good way to start to understand a bit better how to improve it.

Related

Add custom spacing or gaps between bars in barplot ggplot

Is there a way to add custom spacing between bars in a barplot using ggplot function geom_col()?
I want to recreate something like this but in ggplot:
x <- c(2, 4, 7, 5)
barplot(x, space = c(0, 2, 1, 3))
data.frame(y=c(2, 4, 7, 5), x=cumsum(c(0, 2, 1, 3))) |>
ggplot(aes(x, y)) +
geom_col() +
scale_x_continuous()

Turn off clipping of facet labels

I have a faceted graph with a strip label which is clipped due to the width of the facets - I have been removing this clip manually in Inkscape but would like to do it in R. See this small reproducible example (the figure width is non-negotiable and needs to be exported as a .eps file):
library(tidyverse)
# Build data frame
df <- data.frame(treatment = factor(c(rep("A small label", 5), rep("A slightly too long label", 5))),
var1 = c(1, 4, 5, 7, 2, 8, 9, 1, 4, 7),
var2 = c(2, 8, 11, 13, 4, 10, 11, 2, 6, 10))
# Plot scatter graph with faceting by 'treatment'
p <- ggplot(df, aes(x = var1, y = var2)) +
geom_point() +
facet_wrap(treatment ~ ., ncol = 2)
# Save graph as .eps
ggsave(filename = "Graph1.eps", plot = p, device = "eps", width = 60, height = 60, units = "mm")
What I would like is this, where the facet label extends beyond the width of the facet:
So far I've tried the following from this StackOverflow question:
# This doesn't affect the strip labels
p2 <- p +
coord_cartesian(clip = "off")
ggsave(filename = "Graph.eps", plot = p2, device = "eps", width = 60, height = 60, units = "mm")
# This doesn't affect strip labels and results in a blank white graph when exported using ggsave
p3 <- p
p3$layout$clip = "off"
ggsave(filename = "Graph.eps", plot = p3, device = "eps", width = 60, height = 60, units = "mm")
I also tried this way of turning the layout$clip off from this question but it has the same issues as above with the strip labels still being clipped and ggsave exporting a blank file.
p4 <- ggplot_gtable(ggplot_build(p))
p4$layout$clip[p4$layout$name == "panel"] <- "off"
p4 <- grid.draw(p4)
ggsave(filename = "Graph.eps", plot = p4, device = "eps", width = 60, height = 60, units = "mm")
EDIT: As of ggplot2 3.4.0, this has been integrated.
There is a feature request with an open PR on the ggplot2 github to make strip clipping optional (disclaimer: I filed the issue and opened the PR). Hopefully, the ggplot2 team will approve it for their next version.
In the meantime you could download the PR from github and try it out.
library(ggplot2) # remotes::install_github("tidyverse/ggplot2#4223")
df <- data.frame(treatment = factor(c(rep("A small label", 5), rep("A slightly too long label", 5))),
var1 = c(1, 4, 5, 7, 2, 8, 9, 1, 4, 7),
var2 = c(2, 8, 11, 13, 4, 10, 11, 2, 6, 10))
# Plot scatter graph with faceting by 'treatment'
p <- ggplot(df, aes(x = var1, y = var2)) +
geom_point() +
facet_wrap(treatment ~ ., ncol = 2) +
theme(strip.clip = "off")
ggsave(filename = "Graph1.eps", plot = p, device = "eps", width = 60, height = 60, units = "mm")

Changing legend labels in ggplotly()

I have a plot of polygons that are colored according to a quantitative variable in the dataset being cut off at certain discrete values (0, 5, 10, 15, 20, 25). I currently have a static ggplot() output that "works" the way I intend. Namely, the legend values are the cut off values (0, 5, 10, 15, 20, 25). The static plot is below -
However, when I simply convert this static plot to an interactive plot, the legend values become hexadecimal values (#54278F, #756BB1, etc.) instead of the cut off values (0, 5, 10, 15, 20, 25). A screenshot of this interactive plot is shown below -
I am trying to determine a way to change the legend labels in the interactive plot to be the cut off values (0, 5, 10, 15, 20, 25). Any suggestions or support would be greatly appreciated!
Below is the code I used to create the static and interactive plot:
library(plotly)
library(ggplot2)
library(RColorBrewer)
set.seed(1)
x = abs(rnorm(30))
y = abs(rnorm(30))
value = runif(30, 1, 30)
myData <- data.frame(x=x, y=y, value=value)
cutList = c(5, 10, 15, 20, 25)
purples <- brewer.pal(length(cutList)+1, "Purples")
myData$valueColor <- cut(myData$value, breaks=c(0, cutList, 30), labels=rev(purples))
# Static plot
sp <- ggplot(myData, aes(x=x, y=y, fill=valueColor)) + geom_polygon(stat="identity") + scale_fill_manual(labels = as.character(c(0, cutList)), values = levels(myData$valueColor), name = "Value")
# Interactive plot
ip <- ggplotly(sp)
Label using the cut points and use scale_fill_manual for the colors.
cutList = c(5, 10, 15, 20, 25)
purples <- brewer.pal(length(cutList)+1, "Purples")
myData$valueLab <- cut(myData$value, breaks=c(0, cutList, 30), labels=as.character(c(0, cutList)))
# Static plot
sp <- ggplot(myData, aes(x=x, y=y, fill=valueLab)) + geom_polygon(stat="identity") + scale_fill_manual(values = rev(purples))
# Interactive plot
ip <- ggplotly(sp)

offsetting the mean on a scatter plot?

the figure wth offset points but mean in the middle
I'm plotting two sets of data on the same plot, distinguishing the two sets by using different pch and by offsetting them. I also want to plot the mean of both sets of data but so far I've only been able to offset the data points, not the means. This is my code
points(jitter(as.numeric(gen$genord)-0.1,0.1),ai$propaiacts, pch=15,col="dimgray",cex=1)
points(jitter(as.numeric(ugen$genord)+0.1,0.1),uai$propuaiacts, pch=6)
s=split(gen$propaiacts,gen$gencode)
points(jitter(sapply(s, mean)+0.5,0.5),pch="__", cex=2)
s=split(ugen$propuaiacts,ugen$gencode)
points(jitter(sapply(s, mean)-0.1,0.1),pch="__", cex=2)
this is the relevant data:
dput(c(gen$genord,gen$propaiacts))
c(3, 1, 2, 3, 3, 1, 1, 2, 1, 2, 1, 2, 13.5986733, 6.6115702,
9.2198582, 0.6001775, 1.0177719, 6.4348071, 10.0849649, 16.5116934,
11.00971, 14.2514897, 4.366077, 7.3884464)
> dput(c(ugen$ugenord,ugen$propuaiacts))
c(3, 1, 2, 3, 3, 1, 1, 2, 1, 2, 1, 2, 1, 9.4512195, 6.3064133,
7.2121554, 0.6486974, 1.0140406, 5.9735066, 10.076442, 12.5423729,
9.6563923, 13.3744272, 4.4930535, 5.3341665, 21.0191083)
using your code and dataset was difficult, so I will use the iris dataset and hopefully it will help you started. As an alternative to your base R, I used ggplot2. I only converted the data from wide to long. And then I just added position = position_dodge(width = 1) to the geom_point() expression. To add the mean for each group (black dot), I summarised the dataset iris_melt. Hope it will help you to get what you want.
iris_melt <- melt(iris, id.vars=c("Species"))
iris_melt_s <- ddply(iris_melt, c("Species", "variable"), summarise,
meanv = mean(value))
iris_melt <- melt(iris, id.vars=c("Species"))
ggplot(data=iris_melt, aes(x=variable, y=value, group=Species, color=Species, shape=Species)) +
geom_point(position = position_dodge(width = 0.5)) +
geom_point(data=iris_melt_s, aes(x=variable, y=meanv, group=Species, color=Species), color="black", position = position_dodge(width = 0.5))
i realised that I could simply specify the number of categories on the x and then shift it. It's a bit manual, but it worked for now. s=split(ai$propaiacts,ai$recallord) points(c(1,2,3)-0.1,sapply(s, mean), pch="__", cex=2)

left/right bottom/top justification of tiles in ggplot2

Using ggplot2 geom_tile, the default location of the tiles is centred on values of x and y. Is there a way to get x and y values to be the bottom left corner of each tile.
From http://docs.ggplot2.org/current/geom_tile.html
x.cell.boundary <- c(0, 4, 6, 8, 10, 14)
example <- data.frame(
x = rep(c(2, 5, 7, 9, 12), 2),
y = factor(rep(c(1,2), each=5)),
z = rep(1:5, each=2),
w = rep(diff(x.cell.boundary), 2)
)
qplot(x, y, fill=z, data=example, geom="tile")
I do not like my answer, but I'll post it anyway while waiting for a better solution. I transform the data (x-axis +1 and y-axis +0.5) and use the real data as axis breaks.
example <- data.frame( x = rep(c(3, 6, 8, 10, 13), 2), y = (rep(c(1.5,2.5), each=5)), z = rep(1:5, each=2))
ggplot(example)+ geom_tile(aes(x,y,fill=z)) +
scale_x_continuous(breaks=c(2, 5, 7, 9, 12))+
scale_y_continuous(breaks=c(1,2))

Resources