Search code examples
rplotgraphics

Visualization of graphs according to the size of the data


I am making some graphs using different datasets, but when I change the data the graph loses its shape and does not look good. I don't know if there is a way to write something in the code to make the graph take its shape according to the data or how to fix it.

id_year <- factor(2020:2024)

plot(id_year, acum[1, ], type="l", lwd=2, xlim=c(0, 6), 
     ylim=c(40, 80), axes=F, xlab="", ylab="")

id_col <- c("black", "red", "blue", "green", "orange")

for(i in 1:4){
  lines(id_year, acum[i+1, ], col=id_col[i+1], lwd=2)
}

id_col2 <- c("black", "red", "blue", "green", "orange")

for(i in 1:5){
  points(id_year, acum[i, ], pch=15, col=id_col2[i])  
}

axis(1, pos=40, lwd=2, at=c(1:5), labels=c(id_year), font=2)

axis(2, pos=0, at=seq(40, 55, by=5), lwd=2, font=2, las=2)

arrows(0, 40, 6, 40, length=0.15, angle=15, lwd=2)
arrows(0, 40, 0, 60, length=0.15, angle=15, lwd=2)

title(main="Resultados Prueba Saber 11 Año 2018-2022")
title(main="Instituto José Antonio Galán", line=0.5)
title(xlab="Años", font.lab=2)
title(ylab="Puntajes", font.lab=2, line=1)

legend("top", lty=1, col=id_col2, lwd=2, pch=15, 
       legend=c("Lectura", 
                "Matemáticas", 
                "Sociales", 
                "Naturales", 
                "Inglés"), 
       horiz=T, 
       bty="l", bg="lightblue", text.font=2, 
       text.col=id_col2)

text(id_year, acum[1, ], pos=3, font=2, cex=0.8, labels=acum[1, ])
text(1, acum[2, 1], pos=3, font=2, cex=0.8, labels=acum[2, 1], 
     col="red")

text(2, acum[2, 2], pos=2, font=2, cex=0.8, labels=acum[2, 2], 
     col="red")

text(3, acum[2, 3], pos=3, font=2, cex=0.8, labels=acum[2, 3], 
     col="red")

text(4, acum[2, 4], pos=3, font=2, cex=0.8, labels=acum[2, 4], 
     col="red")

text(5, acum[2, 5], pos=4, font=2, cex=0.8, labels=acum[2, 5], 
     col="red")

text(id_year[-3], acum[3, -3], pos=3, font=2, cex=0.8, labels=acum[3, -3], 
     col="blue")

text(id_year[3], acum[3, 3], pos=1, font=2, cex=0.8, labels=acum[3, 3], 
     col="blue")

text(id_year[1], acum[4, 1], pos=2, font=2, cex=0.8, labels=acum[4, 1], 
     col="green")

text(id_year[5], acum[4, 5], pos=3, font=2, cex=0.8, labels=acum[4, 5], 
     col="green")

text(id_year[3], acum[4, 3], pos=1, font=2, cex=0.8, labels=acum[4, 3], 
     col="green")

text(id_year[4], acum[4, 4], pos=3, font=2, cex=0.8, labels=acum[4, 4], 
     col="green")

text(id_year, acum[5, ], pos=1, font=2, cex=0.8, labels=acum[5, ], 
     col="orange")

[Plot](https://i.sstatic.net/Cb0HQkKr.png)

I tried changing the values in X - Y and it improved a little but not completely. The lines of the graphs still overlap.

data

acum <- structure(list(med_res_galan_2018 = c(57, 60, 52, 57, 56), med_res_galan_2019 = c(62, 
62, 57, 59, 60), med_res_galan_2020 = c(60, 61, 56, 58, 54), 
    med_res_galan_2021 = c(59, 58, 53, 56, 54), med_res_galan_2022 = c(60, 
    60, 55, 59, 57)), class = "data.frame", row.names = c("Lectura", 
"Matemáticas", "Sociales", "Naturales", "Inglés"))

Solution

  • This is much easier using matplot since you're essentially dealing with a matrix-like structure, just use as.matrix(). type='o' plots both, lines and points. Code the xlim/ylim dynamically to allow them adapt to new data. In text you can put in matrices. For arrows use par()$usr giving the margin positions of the plot. Put the code in a function plot_acum and use another device such as the png or 'pdf' to always get same size (the RStudio window can be considered a rough preview). You can play a little with the scaling factors I've used and fine-tune it.

    plot_acum <- \(data, id_col=c("black", "red", "blue", "green", "orange")) {
      matplot(as.matrix(data), type='o', lty=1, lwd=2, pch=15, col=id_col, 
              xlim=c(.5, ncol(data) + .5), ylim=c(min(data)*.95, max(data)*1.075),
              ann=FALSE, axes=FALSE)
      title(main="Resultados Prueba Saber 11 Año 2018-2022")
      text(x=col(data), y=t(data)*1.005, pos=rep_len(1:3, ncol(data)), labels=t(data), 
           col=id_col, font=2)
      axis(1, axTicks(1), labels=gsub('.*_', '', colnames(data)), lwd=2, font=2)
      axis(2, las=1, lwd=2, font=2)
      mtext('Años', 1, 2.5, font=2); mtext('Puntajes', 2, 2.5, font=2)
      pu <- par()$usr
      arrows(pu[1], pu[3], pu[2], pu[3], length=0.15, angle=15, lwd=2.3, xpd=TRUE)
      arrows(pu[1], pu[3], pu[1], pu[4], length=0.15, angle=15, lwd=2.3, xpd=TRUE)
      legend("top", lty=1, col=id_col, lwd=2, pch=15, cex=.9, 
             legend=c("Lectura", "Matemáticas", "Sociales", "Naturales", "Inglés"), 
             horiz=TRUE, bg="#00808022", text.font=2, text.col=id_col)
    }
    

    Usage

    png('foo.png', 600, 400)
    plot_acum(acum)
    dev.off()
    

    enter image description here

    Test it using a random acum:

    acum <- array(round(runif(prod(dim(acum)), 50, 80)), dim(acum), dimnames(acum))
    

    Data:

    > dput(acum)
    structure(list(med_res_galan_2018 = c(57, 60, 52, 57, 56), med_res_galan_2019 = c(62, 
    62, 57, 59, 60), med_res_galan_2020 = c(60, 61, 56, 58, 54), 
        med_res_galan_2021 = c(59, 58, 53, 56, 54), med_res_galan_2022 = c(60, 
        60, 55, 59, 57)), class = "data.frame", row.names = c("Lectura", 
    "Matemáticas", "Sociales", "Naturales", "Inglés"))