My plot consists of three circles and two points. I am hoping to complete two, seemingly simple but proving difficult, tasks. I am hoping to 1) Create two legends & 2) change the household point's shape, size, and color. The circles generated using the following function...
circleFun <- function(center,diameter, npoints){
# recovered from
# https://stackoverflow.com/questions/6862742/draw-a-circle-with-ggplot2
r = diameter / 2
tt <- seq(0,2*pi,length.out = npoints)
xx <- center[1] + r * cos(tt)
yy <- center[2] + r * sin(tt)
return(data.frame(x = xx, y = yy))
}
I then call the function with 3 different inputs to generate 100 x-y points for each cirlce
A <- circleFun(c(0,0), 1, npoints=100) %>%
cbind("A") %>%
set_names(c("x", "y", "Neighborhood"))
B <- circleFun(c(.5, .5), 1, npoints=100) %>%
cbind("B") %>%
set_names(c("x", "y", "Neighborhood"))
C <- circleFun(c(1, 1), 1, npoints=100) %>%
cbind("C") %>%
set_names(c("x", "y", "Neighborhood"))
neigh <- rbind(A, B, C)
I then create my point data
hh <- as.data.frame(matrix(c(.25,.5,.25,.5,1,2), 2, 3)) %>%
set_names(c("x", "y", "Household"))
Thus far I have two different data sets, both points, both following aes(x,y). However, their grouping is different: the first data set is grouped by "Neighborhood", the second is grouped by "Household".
I then plot what I have thus far..
# Plot Neighborhoods and set up plot specifics
c <- ggplot(data=neigh, aes(x,y, group = Neighborhood, color = Neighborhood)) +
geom_path(size = 1.5) +
xlab("Quality of Public Amenities") +
ylab("Price of Housing") +
ggtitle("Figure 2.5") +
theme(panel.grid = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
plot.title = element_text(hjust=0.5, face = 'bold', size = 14))
# Add corresponding household points
c+geom_point(data=hh, aes(x=x,y=y,group = as.factor(Household), color = as.factor(Household)))
This is my output..
So why am I asking for help here? I am hoping to 1) Create two legends, one for Neighborhood and another for Households & 2) change the household point's shape, size, and color. Due to the fact that their both point plots, R is not letting me separate the aesthetics of the plots (aes()) which is causing me to not fulfill tasks 1 & 2. The example is fully replicable.
Try this. First I use only x and y as global aesthetics. Second instead of mapping Household in geom_point on color I map it on fill which adds a second legend. One drawback of this solution. You have to chose from the filled shapes, e.g. shape 21 for filled points. The size of the points can be set via the size argument, while the colors can be set e.g. via scale_fill_manual.
library(ggplot2)
library(dplyr)
library(purrr)
# Plot Neighborhoods and set up plot specifics
c <- ggplot(data=neigh, aes(x,y)) +
geom_path(aes(group = Neighborhood, color = Neighborhood), size = 1.5) +
xlab("Quality of Public Amenities") +
ylab("Price of Housing") +
ggtitle("Figure 2.5") +
theme(panel.grid = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
plot.title = element_text(hjust=0.5, face = 'bold', size = 14))
# Add corresponding household points
c +
geom_point(data=hh, aes(group = as.factor(Household), fill = as.factor(Household)), shape = 21, color = "transparent", size = 2) +
scale_fill_manual(name = "Household", values = c("black", "orange"))
Created on 2020-03-31 by the reprex package (v0.3.0)
Related
I am making a 2 group dot plot comparing each group for their ability to achieve a certain percentage of 4 different outcomes. Right now I have my graph exactly how I want it showing 2 colors (one for each group) and the mean plus standard deviation in black. My problem is my legend is showing the mean dots as the 2 different groups and I want it to show the group color dots. Any idea how I can fix it without having to change the mean to the color of the groups? The graph and code are attached. Thanks!
####GG Plot Package
library(ggplot2)
####Using tapply function
perc = read.csv("sealedvsunsealed.csv", header=TRUE)
perc
percmean <- tapply(perc$Percentage, list(perc$Group, perc$Hydrogels), mean)
percsd <- tapply(perc$Percentage, list(perc$Group, perc$Hydrogels), sd)
percmean
percsd
####Subseting the data (which function)
GI <- perc[which(perc$Hydrogels == 'Successful \nInjection'),]
A <- perc[which(perc$Hydrogels == 'Aggregation\nObserved'),]
CA <- perc[which(perc$Hydrogels == 'Cylindrical \nAggregates'),]
CLA <- perc[which(perc$Hydrogels == 'Fully Fills\nChannel'),]
GI
A
CA
CLA
####Create an ANOVA table
GI.aov <- aov(Percentage ~ Group, data = GI)
A.aov <- aov(Percentage ~ Group, data = A)
CA.aov <- aov(Percentage ~ Group, data = CA)
CLA.aov <- aov(Percentage ~ Group, data = CLA)
####Conduct a Tukey's multiple comparision procedure
TukeyHSD(GI.aov)
TukeyHSD(A.aov)
TukeyHSD(CA.aov)
TukeyHSD(CLA.aov)
####Grouped Dot Plot with stats added
vF = ggplot(perc, aes(x=factor(perc$Hydrogels, level = level_order), y=Percentage, fill=perc$Group)) +
geom_dotplot(binaxis='y', stackdir='center', position = position_dodge(0.7))+
theme(legend.position = "right", legend.title = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black"),
axis.text = element_text(size = rel(1.5)),
axis.title.y = element_text(size = rel(1.5)))
vF
vF + stat_summary(fun.y=mean, geom ="point", shape=18, size=4, position = position_dodge(0.7)) +
stat_summary(fun.ymin=function(x)(mean(x)-sd(x)),
fun.ymax=function(x)(mean(x)+sd(x)),
position = position_dodge(0.7),
colour = "black",
geom="errorbar", width=0.3, size=1)+
labs(x = NULL)
Data
Graph showing correct layout but incorrect legend
Note you are missing level_order from your code, i guessed it from your plot
level_order = levels(perc$Hydrogels)[c(4,1,2,3)]
If you can do without the legend for the mean (i.e the diamond), you can just do:
vF + stat_summary(fun.y=mean, geom ="point", shape=18, size=4,
position = position_dodge(0.7),show.legend=FALSE) +
new_scale_color()+
stat_summary(fun.ymin=function(x)(mean(x)-sd(x)),
fun.ymax=function(x)(mean(x)+sd(x)),
position = position_dodge(0.7),
colour = "black",
geom="errorbar", width=0.3, size=1)
I would like certain points I have created through ggplot to take labels at the side of the graph but I am not able to do that through my current code.
Ceplane1 is a matrix with two columns and 100 rows ( can take any random numbers). I want to plot column 2 on the x-axis and column 1 on the y-axis with. I have done this part using the below code. Now I want to make changes in the code so that I can put the label at the side of the graph and not on the graph area itself. Additionally, I want to represent the axis in a comma format. you can take result.table[1,1] and result.table[1,3] to be some number and suggest the solution.
ggplot(Ceplane1, aes(x = Ceplane1[,2], y = Ceplane1[,1])) +
geom_point(colour="blue")+geom_abline(slope = -results.table[5,1],intercept = 0,colour="darkred",size=1.25)+
geom_point(aes(mean(Ceplane1[,2]),mean(Ceplane1[,1])),colour="red")+
geom_point(aes(results.table[1,1],results.table[3,1],colour="darkred"))+ggtitle("CE-Plane: Drug A vs Drug P")+
xlab("QALY Difference")+ylab("Cost Difference")+xlim(-0.05,0.05)+ylim(-6000,6000)+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(),plot.background = element_rect(fill = "white", colour = "black", size = 0.5))+
geom_vline(xintercept = 0,colour="black")+geom_hline(yintercept = 0,colour="black")+
geom_label(aes(mean(Ceplane1[,2]),mean(Ceplane1[,1])),label="mean")+
geom_label(aes(results.table[1,1],results.table[3,1]),label="Base ICER")
I want to put the label at the side of the graph and not on the points of the graph itself. Please suggest me a way to do that.
I think the best way is to add the mean and Base ICER points to your dataset. Then add a column for the legend and you will see them show up as matching in the chart and the legend:
library(ggplot2)
set.seed(1)
Ceplane1 <- data.frame(y = rnorm(100),
x = rnorm(100))
results.table <- data.frame(z = rnorm(100))
Ceplane1$Legend <- "Data"
meanPoint <- data.frame(y = mean(Ceplane1[,1]), x = mean(Ceplane1[,2]), Legend = "Mean")
basePoint <- data.frame(y = results.table[3,1], x = results.table[1,1], Legend = "Base ICER")
Ceplane1 <- rbind(Ceplane1, meanPoint)
Ceplane1 <- rbind(Ceplane1, basePoint)
ggplot(Ceplane1, aes(x = x, y = y, color = Legend)) +
geom_point() +
geom_abline(slope = -results.table[5,1],intercept = 0,colour="darkred",size=1.25) +
ggtitle("CE-Plane: Drug A vs Drug P")+ xlab("QALY Difference")+ylab("Cost Difference") +
xlim(-3,3) + ylim(-3,3) +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(),plot.background = element_rect(fill = "white", colour = "black", size = 0.5)) +
geom_vline(xintercept = 0,colour="black") +
geom_hline(yintercept = 0,colour="black")
This gives me the following:
Note that I changed the xlim and ylim to match the random data I created.
I have a vector of 100 values, and I'd like to plot an intensity graph according to the values in a graph equally divided with 10 little squares.
I'm trying to use ggplot2 package in R, but I'm stuck. Below is my code
> vec <- rnorm(100,5,4) #100-vector
> ggplot(NULL) + geom_vline(xintercept = 1:10) + geom_hline(yintercept = 1:10)+
coord_cartesian(xlim = c(.45, 9.55), ylim = c(.45,9.553))+
theme(legend.box.spacing = unit(0, "mm"),
panel.background = element_blank(),
panel.border = element_rect(colour = "black",fill=NA),
axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank()) #the graph with 100 blocks
[enter image description here][1]
I expect plot the colors in this graph according to the values to the "vec" variable, e.g. shades from red to smaller numbers, going dark blue to larger numbers.
I think this is more-or-less what you want. With ggplot, you need to plot data frames, not just random vectors. And we need to create columns to map to the x and y axes:
set.seed(47)
vec <- rnorm(100,5,4)
dd = expand.grid(x = 1:10, y = 1:10)
dd$vec = vec
ggplot(dd, aes(x = x, y = y, fill = vec)) +
geom_tile() +
scale_fill_gradient(low = "firebrick4", high = "dodgerblue2")
You might have better luck with other palettes, e.g., scale_fill_distiller(palette = "Spectral") is pretty nice.
I have issues having the percentage information at the right locations on my pie chart. Could someone very kindly help me on that? Thank you very much!
#sample dataframe
d <- data.frame(facet=c('a','b','c', "d"), value=c('0.46','0.11','0.18', "0.25"))
d$value <- as.numeric(as.character(d$value))
blank_theme <- theme_minimal()+
theme(
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.border = element_blank(),
panel.grid=element_blank(),
axis.ticks = element_blank(),
plot.title=element_text(size=14, face="bold")
)
d$perc <- round(d$value/sum(d$value) * 100,0)
d$pos <- cumsum(d$perc) - sapply(d$perc,function(x) cumsum(x)-0.5*x)
bp <- ggplot(data=d, aes(x="", y=perc, fill=facet))+
geom_bar(width = 1, stat = "identity") +
geom_text(aes(x="", y=pos, label=paste0(perc,"%"))) +
#geom_text(aes(x="", y=value/4+ c(0, cumsum(value)[-length(value)]), label=percent(value/100)))
scale_fill_manual(values = c("a" = "#b2df8a", "b" = "#238b45", "c" = "#636363", "d"="orange"))
bp
pie <- bp + coord_polar("y", start=0) + blank_theme +
theme(axis.text.x=element_blank())
pie
It happens that for some reason ggplot2 goes to the other direction when dealing with labels. Hence, instead using
d$pos <- 100 - (cumsum(d$perc) - sapply(d$perc, function(x) cumsum(x) - 0.5 * x))
gives
This is straightforward to achieve with ggpiestats function. It only requires slight modification to your dataframe-
library(ggstatsplot)
set.seed(123)
# data
d <-
data.frame(
facet = c('a', 'b', 'c', "d"),
value = c(46, 11, 18, 25)
)
# plot with statistical details in the subtitle
ggstatsplot::ggpiestats(data = d,
main = facet,
counts = value)
In case you don't want statistical test details and want to further customize aesthetics of the plot, you can also use ggplot2 functions-
# customizing it further
# change the slice label
ggstatsplot::ggpiestats(data = d,
main = facet,
counts = value,
slice.label = "both",
package = "wesanderson",
palette = "Royal2") +
ggplot2::labs(subtitle = NULL)
Created on 2019-02-09 by the reprex package (v0.2.1)
I'm drawing a slope graph with ggplot, but the labels get clustered together and are not shown properly because of the scale of the two axis.
Any idea?
My code and the graph Is there any way to adjust step scale?
Thanks alot!
#Read file as numeric data
betterlife<-read.csv("betterlife.csv",skip=4,stringsAsFactors = F)
num_data <- data.frame(data.matrix(betterlife))
numeric_columns <- sapply(num_data,function(x){mean(as.numeric(is.na(x)))<0.5})
final_data <- data.frame(num_data[,numeric_columns],
betterlife[,!numeric_columns])
## rescale selected columns data frame
final_data <- data.frame(lapply(final_data[,c(3,4,5,6,7,10,11)], function(x) scale(x, center = FALSE, scale = max(x, na.rm = TRUE)/100)))
## Add country names as indicator
final_data["INDICATOR"] <- NA
final_data$INDICATOR <- betterlife$INDICATOR
employment.data <- final_data[5:30,]
indicator <- employment.data$INDICATOR
## Melt data to draw graph
employment.melt <- melt(employment.data)
#plot
sg = ggplot(employment.melt, aes(factor(variable), value,
group = indicator,
colour = indicator,
label = indicator)) +
theme(legend.position = "none",
axis.text.x = element_text(size=5),
axis.text.y=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(),
axis.ticks=element_blank(),
axis.line=element_blank(),
panel.grid.major.x = element_line("black", size = 0.1),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
panel.background = element_blank())
# plot the right-most labels
sg1 = sg + geom_line(size=0.15) +
geom_text(data = subset(employment.melt, variable == "Life.expectancy"),
aes(x = factor(variable), label=sprintf(" %2f %s",value,INDICATOR)), size = 1.75, hjust = 0)
# plot the left-most labels
sg1 = sg1 + geom_text(data = subset(employment.melt, variable == "Employment.rate"),
aes(x = factor(variable), label=sprintf("%s %2f ",INDICATOR,value)), size = 1.75, hjust = 1)
sg1
Have you tried to set up a scale, for example x (but I think you should do it for y too)
scale_x_continuous(breaks = seq(0, 100, 5))
where 0 - 100 is the range and 5 is the step size. You need to adjust these values according to your graph.
Source