plot()

Esta función gráfica ofrece muchas variantes, dependiendo del tipo de objeto al que se aplique. Es lo que llamamos coerción: la salida depende de los valores que introduzcamos para los argumentos.

Seguramente el caso más simple corresponda a la representación de dos variables numéricas x e y, que nos devolverá su diagrama de dispersión:

# Generamos n valores distribuidos uniformemente entre 1 y 10
n=100
v1=runif(n,0,10)
# Generamos los valores de y como una transformación lineal
# de los valores de x, más una componente aleatoria
v2=2*v1+rnorm(n)
plot(v1,v2)

Podemos personalizar el gráfico, modificando la forma de los puntos con pch1

su tamaño con cex (que toma el valor 1 por defecto)

y su color, con los parámetros col y bg (por ejemplo usando los números del 1 al 8,

con la función colors(),

el nombre del color2,

##  [1] "white"         "aliceblue"     "antiquewhite"  "antiquewhite1"
##  [5] "antiquewhite2" "antiquewhite3" "antiquewhite4" "aquamarine"   
##  [9] "aquamarine1"   "aquamarine2"   "aquamarine3"   "aquamarine4"  
## [13] "azure"         "azure1"        "azure2"        "azure3"

el valor HEX del color, col = "#0000FF"3, o bien el valor RGB, haciendo uso de la función rgb, que toma la intensidad de colores rojo, verde y azul como argumentos. Su sintasxis es la siguiente:

rgb(red, green, blue, alpha, names=NULL, maxColorValue = 1)`

De forma predeterminada, estos valores se encuentran entre 0 y 1. Esta configuración predeterminada se puede cambiar con el argumento maxColorValue para tener valores entre 0 y el valor que especifiquemos (maxColorValue = 255, es el estándar para la representación del color RGB). Esta función también permite cambiar la transparencia del color, con el argumento alpha, que toma valores desde 0 (completamente transparente) hasta 1.

La nueva gráfica sería:

plot(v1,v2,pch=21,col="red",bg="gray",cex=2/3)

También podemos ponerle un título y/o subtítulo y etiquetas a los ejes:

plot(v1,v2,pch=21,col="red",bg="gray",cex=2/3,
     main="Mi primer gráfico", xlab="x", ylab="y")

y darle formato al texto con family y font (en el siguiente ejemplo elegimos el tipo de letra Times New Roman4 y lo destacamos en negrita):

plot(v1,v2,pch=21,col="red",bg="gray",cex=2/3,
     main="Mi primer gráfico", xlab="x", ylab="y",
     family="Times New Roman" , font=2)

R facilita la creación de gráficos más elaborados, añadiendo a los gráficos de alto nivel gráficos de bajo nivel. Por ejemplo, podríamos estar interesados en añadir la recta de regresión muestral que ajusta por mínimos cuadrados nuestro conjunto de datos, representarla junto a ellos e incluir su expresión:

# Estimamos la recta de regresión muestral y guardamos la salida 
# en el objeto regresion, para poder utilizarla posteriormente
regresion<-lm(v2~v1)
# Representamos el conjunto de datos
plot(v1,v2,pch=21,col="red",bg="gray",cex=2/3,
     main="Mi primer gráfico", xlab="x", ylab="y",
     family="Times New Roman" , font=2)
# Añadimos la recta de regresión muestral
abline(regresion)
# Añadimos la expresión de la recta de regresión muestral
text(6,5,paste("y = ",round(coef(regresion)[2],2),
               "x +", round(coef(regresion)[1],2)))

Como ya hemos mencionado, la función plot devuelve distintos tipos de gráficos según los valores sobre los que la evaluemos. Por ejemplo, si convertimos la variable v1 en un factor (as.factor(trunc(v1))) muestra un diagrama de barras:

plot(as.factor(trunc(v1)))

Si la evaluamos sobre un único argumento numérico, lo representa como una secuencia:

plot(v1)

que podemos personalizar representando líneas en vez de puntos

plot(v1,type="l")

o ambos

plot(v1,type="b")

con el formato que nos parezca más adecuado gracias al argumento lty

plot(v1,type="b",
     lty=3, pch=16, col="red")

También nos permite representar una función, por ejemplo \(f(x)=x \sin^2(x)\),

# Definimos la función
f=function(x)
  x*sin(x)^2
# Representamos f(x) desde 0 hasta 10
plot(f,0,10, main=expression(f(x)==xsin(x)^2))

O varias funciones juntas:

# Definimos la función
f=function(x)
  x*sin(x)^2
g=function(x)
  2*x*sin(x)^2
# Representamos f(x) desde 0 hasta 10
plot(f,0,10)
plot(g,0,10, add=TRUE, col="red")

El gráfico que aparece por defecto es claramente mejorable. Por ejemplo, podemos personalizar la región de dibujo, para ver las curvas completas

# Definimos la función
f=function(x)
  x*sin(x)^2
g=function(x)
  2*x*sin(x)^2
# Representamos f(x) desde 0 hasta 10
plot(f,0,10, ylim=c(0,16))
plot(g,0,10, add=TRUE, col="red")

y añadir una leyenda para identificar las funciones

# Definimos la función
f=function(x)
  x*sin(x)^2
g=function(x)
  2*x*sin(x)^2
# Representamos f(x) desde 0 hasta 10
plot(f,0,10, ylim=c(0,16), lty=2)
plot(g,0,10, add=TRUE, col="red")
legend("topleft", c("f(x)","g(x)"), 
       col = c("black","red"), lty = c(2, 1), 
       merge = TRUE, bg = "gray90")


hist()

La forma habitual de representar un conjunto de datos numérico para observar su distribución es con un histograma. Podemos crearlo con la función hist(), que siempre nos pide como argumento un vector numérico x, mientras que el resto son opcionales.

# Generamos un conjunto de datos con distribución normal 
x=rnorm(100)
hist(x)

Podemos modificar fácilmente su estilo añadiendo parámetros gráficos (algunos de los cuales ya conocemos y otros son propios de esta función como el número de intervalos breaks o el tipo de frecuencias representadas freq)

Cambiar el tipo de frecuencias (absolutas por defecto), solo modifica la escala del eje vertical, pero no la forma del histograma:

# Generamos un conjunto de datos con distribución normal 
x=rnorm(100)
hist(x, freq =FALSE)

No ocurre lo mismo cuando forzamos el número de intervalos5 en los que agrupar los valores a representar:

hist(x, freq=FALSE, breaks=20,
     main="Histograma",ylab="Frecuencia relativa", col=rgb(0,0.5,0.5))

Como la forma del histograma depende de los intervalos, suele ser muy útil representar su densidad:

hist(x, freq=FALSE, breaks=20,
     main="Histograma",ylab="Frecuencia relativa", col=rgb(0,0.75,0.75))
lines(density(x),lty="dotted",lwd=2)

Otra cuestión interesante puede ser comparar el histograma con una distribución teórica, superponiéndola a éste. En el ejemplo con el que estamos trabajando, vamos a comparar con la curva de la densidad normal estándar (que es de la que hemos simulado los valores de x):

hist(x, freq=FALSE, breaks=20,
     main="Histograma",ylab="Frecuencia relativa", col=rgb(0,0.95,0.95))
curve(dnorm, lty="dotdash",lwd=3, add=TRUE)

Si la muestra fuese más grande, ambas distribuciones se parecerían mucho más:

# Generamos un conjunto de datos mucho más grande con distribución normal estándar
x=rnorm(10^6)
# Representamos el histograma de frecuencias relativas
hist(x, freq=FALSE,
     main="Histograma",ylab="Frecuencia relativa")
# Añadimos la curva de la densidad normal estándar
curve(dnorm, add=TRUE, col="red", lwd=2)

Como con cualquier otra función, podemos consultar todas sus opciones con ?hist()


boxplot()

Los boxplot, o diagrama de caja y bigotes, son representaciones gráficas que permiten resumir las principales características de los datos (acerca de su simetría, dispersión, posición y presencia de valores atípicos). La caja comienza en el primer cuartil y termina en el tercero (por lo que contendrá el 50% de los datos centrales), con una línea dentro para representar la mediana. A cada lado de la caja se dibuja un segmento con los datos más alejados, sin contar con los valores atípicos (que aparecen como círculos, caso de existir).

# La siguiente instrucción permite representar una matriz de gráficos
# En este caso, vamos a representar dos gráficos en una fila
par(mfrow=c(1,2))
x=rnorm(100)
# Primer boxplot
boxplot(x)
# Segundo boxplot (con los mismos datos, añadiendo un dato atípico)
boxplot(c(x,5))

Podemos representar los intervalos de confianza al 95% para la mediana, estableciendo el argumento notch como TRUE.

par(mfrow=c(1,2))
x=rnorm(100)
boxplot(x,notch=TRUE)
# Añadimos un dato atípico
boxplot(c(x,5),notch=TRUE)

Este tipo de gráficos resulta especialmente útil para comparar comportamientos6.

# Generamos tres secuencias de valores de sendas distribuciones
# como si provinieran de sendos procesos A, B y C
xA=rnorm(100,1,2)
xB=rnorm(100,3,1/2)
xC=runif(100,0,6)
datos=data.frame(x=c(xA,xB,xC),Proceso=rep(c("A","B","C"),c(100,100,100)))
boxplot(x~Proceso, data=datos,notch=TRUE)

Una limitación de este tipo de gráficos es que no están diseñados para detectar multimodalidad, por lo que puede ser recomendable combinarlos con el histograma o la curva de densidad 7. Veamos cómo hacerlo:

xA=rnorm(1000,1,1/2)
xB=rnorm(1000,5,2)
x=c(xA,xB)
# Histograma
hist(x,probability=TRUE, 
     main="", xlab="",ylab="",axes=FALSE,
     col=rgb(0.5,0,0.5, alpha=0.5),breaks=40)
# Eje
axis(1)
# Densidad
lines(density(x), col="red", lwd=2)
# Boxplot
par(new=TRUE)
boxplot(x, horizontal=TRUE, axes=FALSE,
        col=rgb(0,0,0.15, alpha=0.25))


barplot() y pie()

Cuando una variable es cualitativa o numérica, pero toma pocos valores, es habitual representarla con un gráfico de barras o de sectores.

# Leemos el conjunto resumido de microdatos del INE sobre uso de TICs
# Si vas a ejecutar la línea siguiente, debes cambiar la ruta mostrada
# por la ruta donde esté alojado el conjunto de datos en tu ordenador
# Si estás en el mismo directorio, solo tendrás que escribir datosTICr
# (el nombre del archivo)
load("/Users/maribelparraarevalo/Library/Mobile Documents/com~apple~CloudDocs/GraficosR/Datos/datosTICr")
str(datosTIC)
## 'data.frame':    15027 obs. of  7 variables:
##  $ Edad        : num  98 71 51 81 76 76 72 59 71 83 ...
##  $ Sexo        : Factor w/ 2 levels "Hombre","Mujer": 2 2 2 2 1 1 1 1 2 2 ...
##  $ Nivel       : num  1 1 7 1 1 1 1 3 1 1 ...
##  $ NCompras    : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ ValorCompras: num  NA NA NA NA NA NA NA NA NA NA ...
##  $ UsoInternet : Factor w/ 3 levels "Menos de 3 meses",..: NA NA 1 NA NA NA 1 1 NA NA ...
##  $ Confianza   : Factor w/ 3 levels "Poco o nada",..: NA NA 2 NA NA NA 1 1 NA NA ...
head(datosTIC)
# Diagrama de barras
barplot(table(datosTIC$Confianza),
        col=c("#CCFF99","#FFFF99","#9999FF"))

# Diagrama de sectores
pie(table(datosTIC$Confianza),
        col=c("#CCFF99","#FFFF99","#9999FF"))

Podemos incluir un segundo factor y representar un diagrama de barras apiladas de frecuencias absolutas:

x=table(datosTIC$Sexo, datosTIC$Confianza)
barplot(x,
        col=c("#CCFF99","#9999FF"))

Añadir una leyenda suele ayudarnos a entender mejor un gráfico

barplot(x,
        col=c("#CCFF99","#9999FF"))
legend("topright",legend=c("Hombre","Mujer"),
       fil=c("#CCFF99","#9999FF"), title="Sexo")

Si nos interesa representar frecuencias relativas en vez de frecuencias absolutas o recuentos, usaremos la función prop.table() pudiendo elegir si las calculamos por fila (1), por columna (2) o usando toda la tabla como grupo si no escribimos nada.

barplot(prop.table(x),
        col=c("#CCFF99","#9999FF"))

barplot(prop.table(x,margin=1),
        col=c("#CCFF99","#9999FF"))

barplot(prop.table(x,margin=2),
        col=c("#CCFF99","#9999FF"))


persp()

Con esta función genérica, R nos facilita la tarea de dibujar gráficos en perspectiva de una superficie sobre el plano x–y.

x <- seq(-20, 20, length.out = 51)
y <- x
f<- function(x,y) 
{
  r=sqrt(x^2+y^2)
  sin(r)/r
}
z <- outer(x, y, f)
persp(x, y, z)

Es sencillo modificar la perspectiva, para apreciar mejor la forma de la superficie

persp(x, y, z, theta = 30, phi = 30)

o el aspecto

persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue")

Para aprender un poco más:

EJEMPLO 1: La disposición de las pepitas de un girasol sigue un modelo matemático cuyas coordenadas polares para la semilla \(n-\)ésima son: \[ \begin{array}{l} r=\sqrt{n}\\ \theta=\frac{137.51 \pi r}{180} \end{array} \]. Representar 500 pepitas con círculos.

n <- 1000
r <- 1:n 
theta <- 137.51*pi*r/180
# pasamos a coordenadas cartesianas
x <- cos(theta)*r
y <- sin(theta)*r
plot(x,y,asp=1)


  1. El valor de pch puede ser cualquier símbolo.↩︎

  2. Con la instrucción colors() obtenemos el nombre de todos los colores.↩︎

  3. Por ejemplo, col=1, col="white", col="#FFFFFF" son equivalentes.↩︎

  4. Es necesario que el tipo de letra elegido esté instalada en nuestro ordenador, porque en otro caso no tendría efecto.↩︎

  5. Los posibles valores de breaks son un vector con los puntos de corte (o función que los calcule), un valor numérico (en cuyo caso R lo redondea al valor más próximo que permita construir intervalos sencillos) o el nombre del algoritmo que los calcule ("Sturges", "Scott", "Freedman-Diaconis").↩︎

  6. Si los intervalos de confianza de dos diagramas no se solapan, significa que hay una fuerte evidencia estadística de que las medianas son diferentes.↩︎

  7. Una opción mejor son los diagramas de violín, que veremos más adelante en el curso.↩︎