How to automate vertical bar chart labels? - r

I would like to automate data labels (with % signs) placed on top of the vertical bars produced with the code below. Is there a way to do this?
H <- c(61,89,94,89) # Create the data for the chart.#
M <- c("Pre-Calculus",
"College Algebra",
"Intermediate Algebra",
"Elementary Algebra")
par(mar=c(5.1, 10, 4, 1.1))
barplot(H, col =c("dodgerblue4" ), ylim = range(0,110),
names.arg = M, horiz = F,
family="Arial", border = NA, xlim = range(0,5), las=1,
axes = T, ylab = 'Passing Percent')

Use the text() function. See this SO post for reference
bp <- barplot(H, col =c("dodgerblue4" ), ylim = range(0,110),
names.arg = M, horiz = F,
family="Arial", border = NA, xlim = range(0,5), las=1,
axes = T, ylab = 'Passing Percent')
text(bp, H + 5, paste(H, "%", sep=""))

Related

Moving Bar charts in R away from each other

par(mfrow=c(1,2)) #Plot the two bar charts together
par(mar = c(4, 7, 1, 1)) # Adjust the margins on the four sides of the plot
barplot(height = table(s50_1995$Smoking_status),
main = "Smoking status ", xlab = "", ylab = "", font.lab = 2, col.lab = "Red", cex.lab = 1.5, xlim=c(0,40) ,col = 1:3, horiz = TRUE, las = 2)
# Plot the bar chart indicating the title,the color,
#size and font of the label, the correct x limits,the colors
#for the bars and set the y-axis labels perpendicular to the y axis
mtext("Smoking Status", side=2, line=6) #Set the label for the y axis
mtext("Number of Pupils", side=1, line=2) #Set the label for the x axis
par(mar = c(4, 7, 1, 3)) # Adjust the margins on the four sides of the plot
barplot(height = table(s50_1995$Sport_participation),
main = "Sport participation ",
xlab = "", ylab = "",
font.lab = 2, col.lab = "Red",
cex.lab = 1.5,
xlim=c(0,40) ,
col = 1:3, horiz = TRUE, las = 2)
mtext("Sport participation Status ", side=2, line=6)
mtext("Number of Pupils", side=1, line=2)
par(mfrow=c(1,2))
How do I put these bar charts further away from each other? They are way too close to each other right now
Using some dummy data. it's a balancing act between the allowance for the left margin for the second plot and the location of the axis title for the second plot.
In this case I've increased the size of the left margin in the call to par(mar...) for the second plot to 11 and reduced the mtext position to line 4.
Alternatively you could increase the size of the right margin for the left hand plot.
fruit1 <- c(apple = 40, kiwi = 15, grape = 30)
fruit2 <- c(apple = 20, kiwi = 5, grape = 40)
par(mfrow=c(1,2))
#optionally you could increase the value of the end value to increase the size of the right margin.
par(mar = c(4, 7, 1, 1))
barplot(fruit1,
col="blue",
horiz=TRUE,
las=1)
mtext("Fruit 1", side=2, line=6)
#this is the key line, adjust the second value to increase the gap between the charts
par(mar = c(4, 11, 1, 1))
barplot(fruit2,
col="green",
horiz=TRUE,
las=1)
mtext("Fruit 2", side=2, line=4)
Created on 2021-11-26 by the reprex package (v2.0.1)

Is it possible to remove stacked bar border line?

I've created the stacked bar chart below. I would like to remove the white border line between the two colors of the bar. Is this possible?
counts<- structure(list(
A = c(51,11),
B = c(51,11),
C = c(31,9),
D = c(46,3),
E = c(20,3),
F = c(57,29),
G = c(31,6),
H = c(6,0)),
.Names = c("I'm sure of myself when I do science activities",
"I would consider a career in science",
"I expect to use science when I get out of school",
"Knowing science will help me earn a living",
"I will need science for my future work",
"I know I can do well in science",
"Science will be important to me in my life’s work",
"I cannot do a good job with science"
),
class = "data.frame",
row.names = c(NA, -2L)) #4L=number of numbers in each letter vector#
attach(counts)
print(counts)
# barplot
colors <- c("slategray3","dodgerblue4")
counts <- counts[, order(colSums(counts))]
xFun <- function(x) x/2 + c(0, cumsum(x)[-length(x)])
par(mar=c(2, 22, 4, 2) + 0.1) # this sets margins to allow long labels
byc <- barplot(as.matrix(counts), horiz=TRUE, col=colors, #main="N=35"#,
border=FALSE, las=1, xaxt='n',
ylim = range(0, 12), xlim = range(-10, 100),
width = 1.35)
# labels
labs <- data.frame(x=as.vector(sapply(counts, xFun)), # apply `xFun` here
y=rep(byc, each=nrow(counts)), # use `byc` here
labels=as.vector(apply(counts, 1:2, paste0, "%")),
stringsAsFactors=FALSE)
labs$labels[labs$labels %in% paste0(0:(8*100)/100, "%")] <- "" #masks labels <8
invisible(sapply(seq(nrow(labs)), function(x) # `invisible` prevents unneeded console
output
text(x=labs[x, 1:2], labels=labs[x, 3], cex=.9, font=2, col=0)))
#adds % to scale
scale <- seq(0, 100, by = 20)
axis(side = 1, at = scale, labels = paste0(scale, "%"), cex.axis = 1)
#this adds gridlines
grid(nx = NULL, ny = nx, col = "lightgray", lty = "dotted",
lwd = par("lwd"), equilogs = TRUE)
# legend (set `xpd=TRUE` to plot beyond margins!)
legend(15,14.5, legend=c("Agree","Strongly Agree"),
fill=colors, horiz = T, bty='n', xpd=T)
You could try: border=NA,
byc <- barplot(as.matrix(counts), horiz=TRUE, col=colors, #main="N=35"#,
border=NA, las=1, xaxt='n',
ylim = range(0, 12), xlim = range(-10, 100),
width = 1.35)

How to display legend without masking my spatial plot?

I get a problem for setting the position of legend and wonder if anyone can help.
I follow this example:
http://www.thisisthegreenroom.com/2009/choropleths-in-r/
My code is:
require(maps)
require(ggmap)
library(openxlsx)
rm(list = ls())
map("state", "Arizona")
setwd('M:/SCC/Q-Board')
PM25 <- read.xlsx("PM2.5_Emission_AZ_60 EIS emission sectors.xlsx", sheet = 'Emission_County', colNames = TRUE)
colors = c("#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77",
"#980043")
PM25$colorBuckets <- as.numeric(cut(PM25$PM25, c(0, 5, 10, 20, 30,40, 50)))
map("county",'Arizona', col = colors[PM25$colorBuckets], fill = TRUE,boundary = TRUE, resolution = 0,
lty = 1, projection = "polyconic")
title("PM2.5 Emission by county, 2011")
leg.txt <- c("<5", "5-10", "10-20", "20-30", "30-40", ">40")
legend("bottom", leg.txt, horiz = F, fill = colors,bty="n",title = 'Unit:1000 tons')
Then, the output figure was shown in below. I try to change the position by setting "top", "left"....
But the legend are still overlap with the figure.
Thank you for your help !
It seems to me that you simply run of out the plotting region. This is very common for spatial plot, which will often occupy a significant amount of your plotting domain. I would split the domain into two: one for spatial plot, the other for legend. The following code does this:
## a function to set up plotting region
## l: ratio of left region
## r: ratio of right region
split.region <- function(l, r) {
layout(matrix(c(rep(1, l), rep(2, r)), nrow = 1))
mai <- par("mai")
mai[2] <- 0.1
mai[4] <- 0
par(mai = mai)
}
# use 80% region for main image
# use 20% region for legend
split.region(4, 1)
## produce your main plot
image(x = 0:10/10, y = 0:10/10, matrix(rbinom(100, 1, 0.3), 10), bty= "n", xaxt = "n", yaxt = "n", ann = FALSE, main = "sample plot")
## set up 2nd plot, with nothing
plot(1:2, bty="n", ann=FALSE, xaxt = "n", yaxt = "n", col = "white")
## add your legend to your second plot
leg.txt <- c("<5", "5-10", "10-20", "20-30", "30-40", ">40")
## place legend at bottom left
legend("bottomleft", leg.txt, horiz = F, pch = 15, col = 1:6, bty="n", title = 'Unit:1000 tons', cex = 1.5)
Adjust l, r until you are satisfied.

Put one line chart and bar chart in one plot in R (Not ggplot)?

how to
Combine a bar chart and line in single plot in R (from different data sources)?
Say I have two data sources as:
barData<-c(0.1,0.2,0.3,0.4) #In percentage
lineData<-c(100,22,534,52,900)
Note that they may not be in the same scale.
Can I plot both barData and LineData in one plot and make them good looking ?
I cant use ggplot in this case so this is not a duplicated question..
Something like the following:
Maybe this helps as a starting point:
par(mar = rep(4, 4))
barData<-c(0.1,0.2,0.3,0.4) * 100
y <- lineData<-c(100,22,534,900);
x <- barplot(barData,
axes = FALSE,
col = "blue",
xlab = "",
ylab = "",
ylim = c(0, 100) )[, 1]
axis(1, at = x, labels = c("Julia", "Pat", "Max", "Norman"))
ats <- c(seq(0, 100, 15), 100); axis(4, at = ats, labels = paste0(ats, "%"), las = 2)
axis(3, at = x, labels = NA)
par(new = TRUE)
plot(x = x, y = y, type = "b", col = "red", axes = FALSE, xlab = "", ylab = "")
axis(2, at = c(pretty(lineData), max(lineData)), las = 2)
mtext(text="Lines of code by Programmer", side = 3, line = 1)
box()

barplot labels in r: issues with displaying rotated labels using text()

I want to add labels to the columns of my barplot. Since there are 2 groups each pair of columns will share the same label, i.e 7 labels from "dislike very much" to "like very well".
Since labels titles are quite long I intended to rotate them using the text() function but I cannot get it to display correctly. Here is the code:
A <- c(0, 1, 0, 1, 14, 44, 42)
B <- c(0, 0, 0, 2, 14, 41, 45)
x <- rbind(A, B)
dd.names <- c("Dislike very much", "Strongly dislike", "Dislike", "Neither like nor dislike", "Like", "Like well", "Like very well")
bp <- barplot(x,
beside = TRUE, # Plot the bars beside one another; default is to plot stacked bars
space=c(0.2,0.8), # Amount of space between i) bars within a group, ii) bars between groups
legend = c("Fish cake containing sugar kelp", "Control fish cake"),
args.legend = list(x = "topleft", bty = "n", inset=c(0.1, 0.1)), # bty removes the frame from the legend
xlab = "",
ylab = "Number of scores",
ylim = range(0:50), # Expand the y axis to the value 50
main = "Score results from taste experiments of fish cakes")
text(bp, par("usr")[1], pos = 1, offset = 2, labels = dd.names, adj = 0.5, srt = 25, cex = 0.8, xpd = TRUE)
IMO you're better off rotating the graph.
par(mar=c(3,8,1,1),mgp=c(1.5,.5,0))
bp <- barplot(x,
beside = TRUE,
space=c(0.2,0.8),
legend = c("Fish cake containing sugar kelp", "Control fish cake"),
args.legend = list(x = "bottom", bty = "n", inset=c(0.1, 0.1)),
ylab = "",
xlab = "Number of scores",
xlim = range(0:50), # Expand the y axis to the value 50
main = "Score results from taste experiments of fish cakes",
horiz = TRUE)
text(rep(0,length(dd.names)),bp[1,], par("usr")[3], pos = 2,
labels = dd.names, cex = 0.8, xpd = TRUE)
In an unsolicited act of evangelism, here is a ggplot solution.
library(ggplot2)
library(reshape2) # for melt(...)
library(grid) # for unit(...)
gg <- melt(data.frame(dd.names,t(x)),id="dd.names")
gg$dd.names <- with(gg,factor(dd.names,levels=unique(dd.names)))
ggplot(gg,aes(x=dd.names,y=value))+
geom_bar(aes(fill=variable),stat="identity",position="dodge")+
coord_flip()+
scale_fill_manual(name="",values=c("grey30","grey70"),
labels=c("Fish cake containing sugar kelp", "Control fish cake"))+
labs(title="Score results from taste experiments of fish cakes",
x="",y="Number of scores")+
theme_bw()+theme(legend.position = c(1,0),legend.justification = c(1,0),
legend.key.height=unit(0.8,"lines"))

Resources