Valdarn8
Valdarn8

Reputation: 59

Perform a challenging horizontal dot plot in R showing Min, Max, Mean and StD value

I have to draw a graph to show how much time one patient lives beetween showing symptoms and his death. I found a nice dot plot googling; I adapted it and here is right what I would perform.

img

The grey line shows the standard deviation, the circle shows the mean and the triangles the min and max values.

To try, I prepared my dataset as follow:

> structure(REx)
   Symptom Treatment     Mean    STD    Max Min
1       E1  Treated     4.44     1.39     6   1
2       E2  Treated     3.66     0.83     4   2
3       E3  Treated     3.50     1.94     7   1
4       E4  Treated     3.77     1.23     6   1
5       E5  Treated     3.20     2.16     6   1
6       E1   UTC        1.86     1.25     6   1
7       E2   UTC        1.96     1.09     5   1
8       E3   UTC        1.75     1.38     7   1
9       E4   UTC        1.95     1.23     6   1
10      E5   UTC        1.77     0.85     4   1

I tried using ggdotchart command but I haven't been able to get a plot. Anyone have suggestion?

Upvotes: 2

Views: 703

Answers (2)

Karolis Koncevičius
Karolis Koncevičius

Reputation: 9656

Here is a first draft with base plotting:

REx$Symptom <- factor(REx$Symptom)
REx$Color   <- ifelse(REx$Treatment == "Treated", "red", "blue")


par(mgp=c(2,0.5,0), las=1, cex.axis=0.8, tck=-0.01, yaxs="i", xaxs="i")

plot.new()
plot.window(xlim=range(0, REx$Max+1), ylim=range(0, as.numeric(REx$Symptom)+1))

abline(h=REx$Symptom, col="grey", lty=3, lwd=0.5)
abline(v=0:ceiling(max(REx$Max)), col="grey", lwd=1.5)

segments(REx$Mean - REx$STD, as.numeric(REx$Symptom), REx$Mean + REx$STD, col=adjustcolor("grey", 0.5), lwd=5)
points(REx$Mean, REx$Symptom, pch=19, col=REx$Color)
points(REx$Min,  REx$Symptom, pch=17, col=REx$Color)
points(REx$Max,  REx$Symptom, pch=17, col=REx$Color, cex=1.5)

axis(1, at=1:ceiling(max(REx$Max)))
axis(3, at=1:ceiling(max(REx$Max)), label=NA)
axis(2, at=REx$Symptom, label=REx$Symptom)
box(lwd=1.5)

legend(6.5, 3, legend=paste(c("Mean", "Max", "Min", "SD"), "Treated"), cex=0.8, bg="white",
       pch=c(19,17,17,NA), pt.cex=c(1,1.5,1,NA), lwd=c(NA,NA,NA,2), col=c("red", "red", "red", "grey")
       )
legend(6.5, 1.5, legend=paste(c("Mean", "Max", "Min", "SD"), "UTC"), cex=0.8, bg="white",
       pch=c(19,17,17,NA), pt.cex=c(1,1.5,1,NA), lwd=c(NA,NA,NA,2), col=c("blue", "blue", "blue", "grey")
       )

image

Upvotes: 2

&#201;rico Patto
&#201;rico Patto

Reputation: 1015

I did a basic version for you to customize. I myself enjoy making functional more than elegant solutions (it comes easier), so this isn't using any fancy functions, just the basics.

REx2 <- REx %>%
  gather(key = "StatsType", value = "Value", -c(1:2, 4))

ggplot()+
  geom_linerange(data = REx, aes(xmin = Mean-STD, xmax = Mean+STD, y = Symptom), colour = "gray", size = 1.5)+
  geom_point(data = REx2, aes(x = Value, y = Symptom, colour = Treatment, size = StatsType, shape = StatsType))+
  scale_shape_discrete(limits = c("Mean", "Max", "Min"), breaks = c(19, 17, 17), labels = c("Mean", "Max", "Min"), guide = "legend")+
  scale_size_discrete(limits = c("Mean", "Max", "Min"), breaks = c(1, 2, 1))+
  theme_bw()

Notice, however, that I agree with the warning:

Warning message: Using size for a discrete variable is not advised.

First, I made a second data frame using library(dplyr) and library(tidyr) (both part of tidyverse, as like ggplot2) where the mean, the max and min would be on one column. Than I do that plot, only changing shape and size to fit what you wanted by type. However, the linerange seemed to demand the original data frame, which is why I kept it.

Upvotes: 1

Related Questions