Overlaying geom_point layer on a geom_boxplot - r

Really struggling with this.
a & b are actual datasets in the real world, a being extremely large. I get an error ggplot2 doesn't know how to deal with data of class uneval. What I'm trying to do is overlay a single point from a second data set on to the boxplot to highlight how one particular sample compared to a universe.
Any idea what I'm doing wrong? How can I fix it?
a = data.frame(YTD.Retn=runif(1000,-10,10),sector="a")
a = rbind(a,data.frame(YTD.Retn=runif(1000,-10,10),sector="b"))
a = rbind(a,data.frame(YTD.Retn=runif(1000,-10,10),sector="c"))
a = rbind(a,data.frame(YTD.Retn=runif(1000,-10,10),sector="d"))
a = rbind(a,data.frame(YTD.Retn=runif(1000,-10,10),sector="e"))
a = rbind(a,data.frame(YTD.Retn=runif(1000,-10,10),sector="f"))
a = rbind(a,data.frame(YTD.Retn=runif(1000,-10,10),sector="g"))
b = data.frame(sector=c("a","b","c","d","e","f","g"),YTD.Retn=c(5,6,7,3,2,-1,-5))
p1 =ggplot(a,aes(factor(sector),YTD.Retn,fill=factor(sector))) + geom_boxplot() +
scale_fill_discrete(guide=F) +
geom_point(b,aes(factor(sector),YTD.Retn))
plot(p1)

You need to name the argument data when called within a geom_...() call. Naming arguments is good practice in general (if somewhat timeconsuming)
p1 =ggplot(data = a, aes(x = factor(sector), y = YTD.Retn, fill=factor(sector))) +
geom_boxplot() +
scale_fill_discrete(guide=F) +
geom_point(data = b, aes(x= factor(sector),y= YTD.Retn))
plot(p1)

Related

ggplot - is it at all possible to draw multiple lines without grouping data

I am currently writing a theoretical article where no data is used and unfortunately I must say that I find ggplot hard to use in such applications for showing theoretical examples. I've been using ggplot for years on real, empirical data and there I liked ggplot very much. However, consider my current case. I am trying to plot two exponential functions together on a graph. One function is 0.5^x and the other one is 0.8^x. In order to produce a ggplot graph, I have to do the following:
x <- 1:20
a <- 0.5^x
b <- 0.8^x
data.frame(x, a, b) %>%
pivot_longer(c(a, b)) %>%
ggplot(aes(x = x, y = value, color = name, group = name))+
geom_line()
Output:
Which completely doesn't correspond to the psychological process in my head to create such a graph - mainly becasue of converting it to the long format to be able to group it.
In my head, I am creating two simple, but distinct curves on the same canvas. So I should be able to use something like:
qplot(x, 0.5^x, geom = "line")+
qplot(x, 0.8^x, geom = "line")
However, that doesn't work because
Can't add `qplot(x, 0.8^x, geom = "line")` to a ggplot object.
Any help with how to create such a simple graph without reshaping the data would be appreciated, thanks.
Using geom_function you could do:
library(ggplot2)
ggplot() +
geom_function(fun = ~ 0.5^.x, mapping = aes(color = "a")) +
geom_function(fun = ~ 0.8^.x, mapping = aes(color = "b")) +
xlim(1, 20)
Created on 2022-05-08 by the reprex package (v2.0.1)
Maybe something like this. It is possible to keep the data in wide format. But generally it is better to bring it long foramt:
library(ggplot2)
ggplot()+
geom_line(aes(x, 0.5^x, color="red"))+
geom_line(aes(x, 0.8^x, color = "blue"))+
scale_color_identity()

R code of scatter plot for three variables

Hi I am trying to code for a scatter plot for three variables in R:
Race= [0,1]
YOI= [90,92,94]
ASB_mean = [1.56, 1.59, 1.74]
Antisocial <- read.csv(file = 'Antisocial.csv')
Table_1 <- ddply(Antisocial, "YOI", summarise, ASB_mean = mean(ASB))
Table_1
Race <- unique(Antisocial$Race)
Race
ggplot(data = Table_1, aes(x = YOI, y = ASB_mean, group_by(Race))) +
geom_point(colour = "Black", size = 2) + geom_line(data = Table_1, aes(YOI,
ASB_mean), colour = "orange", size = 1)
Image of plot: https://drive.google.com/file/d/1E-ePt9DZJaEr49m8fguHVS0thlVIodu9/view?usp=sharing
Data file: https://drive.google.com/file/d/1UeVTJ1M_eKQDNtvyUHRB77VDpSF1ASli/view?usp=sharing
Can someone help me understand where I am making mistake? I want to plot mean ASB vs YOI grouped by Race. Thanks.
I am not sure what is your desidered output. Maybe, if I well understood your question I Think that you want somthing like this.
g_Antisocial <- Antisocial %>%
group_by(Race) %>%
summarise(ASB = mean(ASB),
YOI = mean(YOI))
Antisocial %>%
ggplot(aes(x = YOI, y = ASB, color = as_factor(Race), shape = as_factor(Race))) +
geom_point(alpha = .4) +
geom_point(data = g_Antisocial, size = 4) +
theme_bw() +
guides(color = guide_legend("Race"), shape = guide_legend("Race"))
and this is the output:
#Maninder: there are a few things you need to look at.
First of all: The grammar of graphics of ggplot() works with layers. You can add layers with different data (frames) for the different geoms you want to plot.
The reason why your code is not working is that you mix the layer call and or do not really specify (and even mix) what is the scatter and line visualisation you want.
(I) Use ggplot() + geom_point() for a scatter plot
The ultimate first layer is: ggplot(). Think of this as your drawing canvas.
You then speak about adding a scatter plot layer, but you actually do not do it.
For example:
# plotting antisocal data set
ggplot() +
geom_point(data = Antisocial, aes(x = YOI, y = ASB, colour = as.factor(Race)))
will plot your Antiscoial data set using the scatter, i.e. geom_point() layer.
Note that I put Race as a factor to have a categorical colour scheme otherwise you might end up with a continous palette.
(II) line plot
In analogy to above, you would get for the line plot the following:
# plotting Table_1
ggplot() +
geom_line(data = Table_1, aes(x = YOI, y = ASB_mean))
I save showing the plot of the line.
(III) combining different layers
# putting both together
ggplot() +
geom_point(data = Antisocial, aes(x = YOI, y = ASB, colour = as.factor(Race))) +
geom_line(data = Table_1, aes(x = YOI, y = ASB_mean)) +
## this is to set the legend title and have a nice(r) name in your colour legend
labs(colour = "Race")
This yields:
That should explain how ggplot-layering works. Keep an eye on the datasets and geoms that you want to use. Before working with inheritance in aes, I recommend to keep the data= and aes() call in the geom_xxxx. This avoids confustion.
You may want to explore with geom_jitter() instead of geom_point() to get a bit of a better presentation of your dataset. The "few" points plotted are the result of many datapoints in the same position (and overplotted).
Moving away from plotting to your question "I want to plot mean ASB vs YOI grouped by Race."
I know too little about your research to fully comprehend what you mean with that.
I take it that the mean ASB you calculated over the whole population is your reference (aka your Table_1), and you would like to see how the Race groups feature vs this population mean.
One option is to group your race data points and show them as boxplots for each YOI.
This might be what you want. The boxplot gives you the median and quartiles, and you can compare this per group against the calculated ASB mean.
For presentation purposes, I highlighted the line by increasing its size and linetype. You can play around with the colours, etc. to give you the aesthetics you aim for.
Please note, that for the grouped boxplot, you also have to treat your integer variable YOI, I coerced into a categorical factor. Boxplot works with fill for the body (colour sets only the outer line). In this setup, you also need to supply a group value to geom_line() (I just assigned it to 1, but that is arbitrary - in other contexts you can assign another variable here).
ggplot() +
geom_boxplot(data = Antisocial, aes(x = as.factor(YOI), y = ASB, fill = as.factor(Race))) +
geom_line(data = Table_1, aes(x = as.factor(YOI), y = ASB_mean, group = 1)
, size = 2, linetype = "dashed") +
labs(x = "YOI", fill = "Race")
Hope this gets you going!

Bug in ggplot2?

I'm currently working on plotting simple plots using ggplot2.
The graph looks good, but there is one tiny detail I can't fix.
When you look at the legend, it says "Low n" twice. One of them should be "High n".
Here is my code:
half_plot <- ggplot() +
ggtitle(plot_title) +
geom_line(data = plot_dataframe_SD1, mapping = aes(x = XValues, y = YValues_SD1, color = "blue")) +
geom_line(data = plot_dataframe_SD2, mapping = aes(x = XValues, y = YValues_SD2, color = "green")) +
xlim(1, 2) +
ylim(1, 7) +
xlab("Standard Deviation") +
ylab(AV_column_name) +
scale_fill_identity(name = 'the fill', guide = 'legend',labels = c('m1')) +
scale_colour_manual(name = 'Legend',
values =c('blue'='blue','green'='green'),
labels = c(paste("Low ", Mod_column_name), paste("High ", Mod_column_name))
Here is the graph I get in my output:
So do you know how to fix this?
And there is one more thing that makes me curious: I can't remember that I changes anything in this code, but I know that the legend worked just fine a few days ago. I safed pictures I made wih this code and it looks alright..
Also if you have any further suggestions how to upgrade the graph, these suggestions are very welcome too.
When asking questions, it will help us if you provide a reproducible example including the data. With some sample data, there are a couple ways to fix it.
Sample data
library(dplyr)
plot_dataframe_SD1 = data.frame(XValues=seq(1,2,by=.2)) %>%
mutate(YValues_SD1=XValues*2)
plot_dataframe_SD2 = data.frame(XValues=seq(1,2,by=.2)) %>%
mutate(YValues_SD2=XValues*5)
The simplest way to modify your code is to supply the desired color label in the aesthetic.
Mod_column_name = 'n'
half_plot <- ggplot() +
# put the desired label name in the aesthetic
# link describing the bang bang operator (!!) https://www.r-bloggers.com/2019/07/bang-bang-how-to-program-with-dplyr/ geom_line(data=plot_dataframe_SD1,mapping=aes(x=XValues,y=YValues_SD1,color=!!paste('Low',Mod_column_name))) +
geom_line(data=plot_dataframe_SD2,mapping=aes(x=XValues,y=YValues_SD2,color=!!paste('High',Mod_column_name))) +
scale_color_manual(values=c('blue','green'),
labels=c(paste('Low',Mod_column_name),paste('High',Mod_column_name)))
A more general approach is to join the dataframes and pivot the joined df to have a column with the SD values and another to specify how to separate the colors. This makes it easier to plot without having to make multiple calls to geom_line.
# Join the dfs, pivot the SD columns longer, and make a new column with your desired labels
joined_df = plot_dataframe_SD1 %>% full_join(plot_dataframe_SD2,by='XValues') %>%
tidyr::pivot_longer(cols=contains('YValues'),names_to='df_num',values_to='SD') %>%
mutate(label_name=if_else(df_num == 'YValues_SD1',paste('Low',Mod_column_name),paste('High',Mod_column_name)))
# Simplified plot
ggplot(data=joined_df,aes(x=XValues,y=SD,color=label_name)) +
geom_line() +
scale_color_manual(values=c('blue','green'),
labels=c(paste('Low',Mod_column_name),paste('High',Mod_column_name)))

Add legend to ggplot2 line with point plot

I have a question about legends in ggplot2. I managed to plot two lines and two points in the same graph and want to add a legend with the two colors used. This is the code used
P <- ggplot() + geom_point(data = data_p,aes(x = V1,y = V2),shape = 0,col = "#56B4E9") + geom_line(data = data_p,aes(x = V1,y = V2),col = "#56B4E9")+geom_point(data = data_p,aes(x = V1,y = V3),shape = 1,col = "#009E73") + geom_line(data = data_p,aes(x = V1,y = V3),col = "#009E73")
and the output is
enter image description here
I try to use scale_color_manual and scale_shape_manual and scale_line_manual,but they don't work .
P + scale_color_manual(name = "group",values = c('#56B4E9' = '#56B4E9','#009E73' = '#009E73'),
breaks = c('#56B4E9','#009E73'),labels = c('B','H')) +
I want it like this
Here is the simple data if it can help you.
5 0.49216 0.45148
10 0.3913 0.35751
15 0.32835 0.30361
data_p
I would approach this problem in two steps.
Generally, to get stuff in the guides, ggplot2 wants you to put "aesthetics" like colour inside the aes() function. I typically do this inside the ggplot() rather than individually for each "geom", especially if everything kind of makes sense in a single dataframe.
My first step would be to remake your dataframe slightly. I would use the package tidyr (part of the tidyverse, like ggplot2, which is really nice for reformatting data and worth learning as you go), and do something like this
#key is the new variable that will be your color variable
#value is the numbers that had been in V2 and V3 that will now be your y-values
data_p %>% tidyr::gather (key = "color", value = "yval", V2, V3)
#now, I would rewrite your plot slightly
P<-(newdf %>% ggplot(aes(x=V1,y=yval, colour=color))
#when you put the ggplot inside parentheses,
#you can add each new layer on its own line, starting with the "+"
+ geom_point()
+ geom_line()
+ scale_color_manual(values=c("#56B4E9","#009E73"))
#theme classic is my preferred look in ggplot, usually
+ theme_classic()
)

Y scale on ggplot2 bar graph makes no sense

My bar graph has a weird Y Axis that skips around seemingly at random, from -1.7% to -10.1%, -10.3%, and then to -2%. You can see it below:
Here is my code:
library(ggplot2)
healthd = read.csv("R/states.csv")
states = healthd[[1]]
insuredChange = healthd[[4]]
ggplot(data = healthd, aes(x = states, y = insuredChange)) +
geom_bar(stat="identity") +
theme(axis.text.x=element_text(angle = 90, hjust = 1))
What's going on here? How do I fix it?
Also, how can I get the x axis labels to all be right justified on the same line?
First - what you present isn't a reproducible example and nobody wants to sign up to access your data to help you out...
In your code:
states = healthd[[1]]
and
insuredChange = healthd[[4]]
are assigning the columns to the global environment - they are not changing the name of the values in your data.frame. When you use ggplot it is looking for columns in your data.frame with the names that don't exist - hence the NULL statement
healthd$states = healthd[[1]]
healthd$insuredChange = healthd[[4]]
will change it to something that should work - though I don't have the data so am not completely sure.
This should now generate the figure you want.
ggplot(healthd, aes(states, insuredChange)) +
geom_bar(stat="identity") +
theme(axis.text.x=element_text(angle = 90, hjust = 1))

Resources