Está en la página 1de 123

R presenta gran flexibilidad para trabajar con bases de datos sin implicar

grandes esfuerzos para tal fin. En esta sección se presentarán algunos


ejemplos de cómo trabajar con datos así como la importación de archivos
que se han creado en los siguientes formatos:

 .xls, .xlsx, .csv, .txt

 y, por supuesto, el legendario Copy-Paste que no puede faltar!!!


Para introducir rápidamente un conjunto pequeño de datos en R podemos crear vectores a partir de la función concatenar
"c" tal y como lo hemos visto en las clases anteriores:

> x = c(2,3,0,3,1,0,0,1)
> x
[1] 2 3 0 3 1 0 0 1

Esto genera un vector denominado x con 8 valores.


También podríamos utilizar la función scan()que nos facilita la vida a la hora de hacer copy/paste:

1. Abrir Word y escribir una sucesión de 25 números entre el 0 y 9.


2. Los seleccionamos y copiamos al portapapeles con Ctrl + C
3. Una vez en R escribimos:
 > x = scan() # R queda en espera que peguemos los datos copiados, aparece 1:
 Ctrl + V
 1: 3 4 1 1 3 4 3 3 1 3 2 1 2 1 2 3 2 3 1 1 1 1 4 3 1 # aparece 26:
 finalmente damos y muestra Read 25 items

> x=scan()
1: 3 4 1 1 3 4 3 3 1 3 2 1 2 1 2 3 2 3 1 1 1 1 4 3 1
26:
Read 25 items
Podemos hacer algo de estadística con estos datos
> cumsum(x)
[1] 3 7 8 9 12 16 19 22 23 26 28 29 31 32 34 37 39 42 43 44 45 46 50 53 54

> cor(x,x)
[1] 1

> mean(x)
[1] 2.16
> quantile(x)
0% 25% 50% 75% 100%
1 1 2 3 4

>
quantile(x,probs=c(0.1,0.4,0.9))
10% 40% 90%
1.0 1.6 3.6

> sample(1:10,5,rep=T) muestra de 5 números del 1 al 10 con repetición


[1] 1 5 8 1 7

> sample(1:10,5) muestra de 5 números del 1 al 10 sin repetición


[1] 1 5 9 3 2
> rnorm(5) 5 números aleatorios de la distribución normal estándar
[1] -0.03942804 -0.41947213 -0.22912134 0.41734751 -1.32822353

> rnorm(4,mean=10,sd=3.5) 4 números aleatorios de una dist.normal con media 10 y desviación estándar 3.5
[1] 11.92598 11.80259 14.16484 10.69332

> pnorm(0) probabilidad acumulada hasta 0 de la distribución normal estándar


[1] 0.5
Hasta el momento hemos visto como trabajar con un vector, pero también es habitual
tener que hacer tratamiento de datos sobre tablas que contienen más de una columna
(más de un vector en definitiva). Para facilitar esta tarea, R dispone de los denominados
data frames.

En un Data Frame cada columna puede ser de un tipo diferente: cadenas de caracteres,
números, fechas. Por otra parte, esta estructura de datos permite realizar toda una serie
de operaciones de gran utilidad como cruces entre 2 data frames.
> peso = c(75, 98, 67, 80)

> altura = c(1.75, 1.89, 1.61, 1.77)

> sexo = c("F", "M","M","F")

> personas = data.frame(peso,altura,sexo) # Construye un dataframe con los 3 vectores y


establece como nombre de columna el de las variables

> personas
peso altura sexo
1 75 1.75 F
2 98 1.89 F
3 67 1.61 M
4 80 1.77 F
Podemos hacer algo de estadística básica con estos datos

> mean(peso) calcula la media de la variable peso

[1] 80

> sd(altura) calcula la desviación estándar de la variable altura

[1] 0.1147461

> cor(altura,peso) encuentra la correlación lineal de la variable altura

[1] 0.9594587
> rm(peso) ; rm(altura); rm(sexo) # borra las variables

Otra forma de crear data frames sin nombres de columna es:


Nombre que yo le estoy dando al data freme, NO es un comando o instrucción de R

> df = data.frame(c(1, 2, 3), c(7, 3, 4))

O bien con nombres de columna

> df = data.frame(col1 = c(1, 2, 3), col2 = c(7, 3, 4))


Acceso a elementos

# por ejemplo para seleccionar o mostrar la columna 1, tenemos las siguientes opciones:

> df$col1
> df[ ,1]
> df[["col1"]]
> personas[1]

Podemos hacer algo de estadística con estos datos


Acceso a elementos
Por defecto, las filas se enumeran del 1,....,n

> personas
peso altura sexo
1 75 1.75 F
2 98 1.89 M sin embargo también podemos “asignarles” nombres:
3 67 1.61 M
4 80 1.77 F

> row.names(personas)=c("Maria","Juan","Pedro","Ana")
> personas
peso altura sexo
Maria 75 1.75 F
Juan 98 1.89 M
Pedro 67 1.61 M
Ana 80 1.77 F
Filtros
Le pide a R que seleccione la columna

> personas[personas$sexo == 'F', ]


peso altura sexo
Maria 75 1.75 F
Ana 80 1.77 F

> personas[personas$sexo == 'F' & personas$altura > 1.75,]


peso altura sexo
Ana 80 1.77 F
Filtros La función table de R

> table(sexo) # Contabiliza ocurrencias por sexo


sexo
F M
2 2

> table(sexo, peso) # Contabiliza ocurrencias por sexo y peso

peso
sexo 67 75 80 98
F 0 1 1 0
M 1 0 0 1
• Del menú principal de R seleccionamos Editar

• Posteriormente Editor de datos

Podemos modificar nuestros


datos al editarlos:

• Nos pide el nombre de la base de datos (personas)

• Damos clic en el espacio de la variable var5 y le asignamos el nombre Estudios


• Maria M, Juan P, Pedro P, Ana D
• Del menú principal de R seleccionamos Editar

• Posteriormente Editor de datos


Podemos modificar nuestros datos al editarlos:

> personas
peso altura sexo Estudios
Maria 75 1.75 F M
Juan 98 1.89 M P
Pedro 67 1.61 M P
Ana 80 1.77 F D
• Nos pide el nombre de la base de datos (personas)
> Datos <-matrix(c(20,65,174,22,70,180,19,68,170),nrow=3,byrow=T)
Una matriz creada previamente

La función dimnames funciona asignando a su argumento una lista de dos vectores de caracteres:
los nombres de las filas y de las columnas de la matriz:

dimnames(objeto) = list( vector de nombres de las filas, vector de nombres de las columnas).

UNA VEZ CREADA LA MATRIZ DATOS EN LA DIAPOSITIVA ANTERIOR LE PODEMOS ASIGNA NOMBRES A SUS FILAS Y COLUMNAS

> dimnames(Datos)=list(c("Luis","José","Alex"),c("edad", "peso","altura"))


> Datos
edad peso altura
Luis 20 65 174
José 22 70 180
Alex 19 68 170
Otro uso del copy – paste: es crear un archivo de datos en
excel, copiar las columnas (junto con el encabezado) de datos
que interesan y luego en R escribir.

misdatos = read.delim("clipboard")
> misdatos=read.delim("clipboard")
> misdatos
Dólar Euro
1 18 20
2 19 21
3 20 22
4 17 23
5 16 21
6 15 20
7 13 19
8 18 23
9 19 22
Curso de introducción a R Enero de 2018

Cuando los datos están en formato txt delimitados por tabulaciones, se pueden importar en R utilizando read.delim
o read.table, es importante que en ambas funciones se agregue el argumento sep= " \t" para indicar que las
columnas de datos están separadas por tabulaciones en caso de que el archivo tenga la estructura.

datos.txt <- read.delim("datos.txt", header=T, sep='\t')

G = read.table("c:/datos/glucosa.txt", header = T)

Sesión 2 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

> boxplot(glucosa~enfermera, ylab="valores de glucosa", xlab=“enfermera",col="red" ,data=G)

Valor atípico
Valor máximo

Q3

RIC

mediana
Q1

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Titulo del eje X Titulo dele eje Y Color de la gráfica

> barplot(table(G$enfermera), xlab="enfermera", ylab="Frecuencia",col="blue")

Permite
seleccionar la
variable de la
base de datos

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Tipo de figura

> stripchart(G$temperatura, method = "stack", pch = 2)


El método que se utilizará para separar los puntos
coincidentes. El método predeterminado "overplot"
hace que dichos puntos se sobrescriban, pero también
selecciona la es posible especificar "jitter" para separarlos en
variable de la puntos, o "stack" tiene puntos coincidentes apilados.
base de datos El último método solo tiene sentido para datos muy
granulares.

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

> pie(G$glucosa,labels=G$enfermera)

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

> hist(G$temperatura,col="green")

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

> hist(G$temperatura, probability=TRUE,col="brown")

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

> hist(G$temperatura, probability=TRUE,col="yellow")


> lines(density(G$temperatura), col="red", lwd=2)

Grosor de
la línea

Para visualizar el polígono de densidad


se requiere que el histograma refleje la
probabilidad (density)

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Nos permite observar la distribución de probabilidad y los percentiles, media, etc.

hist.y.boxplot =
function (x,...) {
op <-par(no.readonly=TRUE)
on.exit(par(op))
layout(matrix(c(1,2),2,1),heights=c(3,1))
par(mai=c(1,1,1,1)/2)
hist(x,xlab=FALSE,col=gray(0.95),yaxt='n',...)
rug(x)
boxplot(x,horizontal=TRUE) }

> hist.y.boxplot(G$temperatura)

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

es un gráfico en modo texto similar al histograma pero invertido lateralmente, útil para conjuntos de datos pequeños.

> stem(G$glucosa)

The decimal point is 1 digit(s) to the right of the |

7 | 00455689
8 | 011122244456899
9 | 3369
10 | 26
11 | 5
12 |
13 | 1

Como se puede observar, en el ejemplo debemos considerar que la coma empieza en la | y por tanto tenemos dos puntos en
7 (7.0), ninguno en 12, varios en 8 (8.0, 3 valores en 8.1, otros tres en 8.2 y 8.4, uno en 8.5, etc.) y así sucesivamente. El
gráfico es más representativo si inclinamos la cabeza hacia la derecha.

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

se usan para analizar la asociación de un par de variables de atributo y numéricas.

Visualización de datos de dos variables

◾Gráficos de barras: consideremos nuestra base de datos G, y consideremos las dos variables enfermera y temperatura, para
crear una tabla de contingencia escribimos

> tabla=table(G$enfermera,G$temperatura)
> tabla

35 35.4 35.6 35.8 36 36.2 36.3 36.4 37 37.3 37.5 38


1 0 0 1 0 3 2 1 0 0 1 2 0
2 2 1 0 1 1 1 0 1 2 1 2 1
3 0 0 1 2 0 0 2 1 0 1 0 1

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Como observamos, podemos utilizar de nuevo la función table() para contabilizar el número de apariciones de cada
categoría. Si queremos conocer la probabilidad de caer en cada una de las parejas de categorías:

> options(digits=3) # Limitamos a 3 decimales como máximo


> prop.table(tabla)

35 35.4 35.6 35.8 36 36.2 36.3 36.4 37 37.3 37.5 38


1 0.0000 0.0000 0.0323 0.0000 0.0968 0.0645 0.0323 0.0000 0.0000 0.0323 0.0645 0.0000
2 0.0645 0.0323 0.0000 0.0323 0.0323 0.0323 0.0000 0.0323 0.0645 0.0323 0.0645 0.0323
3 0.0000 0.0000 0.0323 0.0645 0.0000 0.0000 0.0645 0.0323 0.0000 0.0323 0.0000 0.0323

Para visualizar la información mediante un gráfico de barras:

> barplot(table(G$temperatura,G$enfermera),main="Temperatura según enfermera",


+ beside=TRUE,)

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Sesión 4 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Vamos a copiar los datos contenidos en el archivo TIIE-CETES

• Una forma sería:


a) Abrir el archivo y copiar los datos contenidos en las celdas incluyendo los encabezados.
b) Una vez en R escribir datos<-read.delim("clipboard")
c) Para ver si los datos ya están cargados, escribimos su nombre (datos) o View(datos)

Para importar directamente desde Excel o exportar a Excel en su respectivo formato .xls o .xlsx se deben cargar paquetes
adicionales, lo cual no me parece nada atractivo, porque los archivos .txt o .csv funcionan muy bien en todos los softwares
estadísticos y también en Excel mismo, sin embargo, para aquellos que les gusta mantener sus datos en archivos .xls o .xlsx
pueden estar tranquilos porque incluso en ese formato se importa a R.

Para importar archivos de Excel a R se debe instalar el paquete XLConnect disponible en CRAN.

Sesión 2 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

Vamos a copiar los datos contenidos en el archivo TIIE-CETES

• Una forma sería:


a) Abrir el archivo y copiar los datos contenidos en las celdas incluyendo los encabezados.
b) Una vez en R escribir datos<-read.delim("clipboard")
c) Para ver si los datos ya están cargados, escribimos su nombre (datos) o View(datos)

◾Puntos en un plano con línea de regresión: Si entendemos que X es un valor que controlamos e Y un valor que
medimos. Veamos como podemos dibujar una línea en nuestro gráfico que corresponda con la regresión lineal:

Sesión 2 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

> library(MASS) #Cargamos el paquete que contiene la función rlm

> plot(datos$TIIE,datos$CETES)
X Y
> abline(lm(datos$CETES ~ datos$TIIE), col="red") #Línea de regresión
Y X
> abline(rlm(datos$CETES ~ datos$TIIE), col="red", lty=2) #Línea de regresión resistente
Y X

Puntos en un plano con línea de


regresión resistente: línea con
capacidad de "resistir" a la influencia
de un porcentaje determinado de
datos muy dispersos (p.ej. reducir el
efecto que tiene 2 datos puntuales
extremos).

Sesión 2 – Importación y análisis de datos en R


Curso de introducción a R Enero de 2018

"scatterplot" <-
function(x,y,...) {
def.par = par(no.readonly = TRUE)
n<-length(x)
xhist = hist(x,sqrt(n), plot=FALSE)
yhist = hist(y, sqrt(n), plot=FALSE)
top = max(c(xhist$counts, yhist$counts))
xrange = c(min(x),max(x))
yrange = c(min(y),max(y))
nf = layout(matrix(c(2,0,1,3),2,2,TRUE), c(3,1), c(1,3), TRUE)
layout.show(nf)
par(mar=c(3,3,1,1))
plot(x, y, xlim=xrange, ylim=yrange, xlab="x", ylab="y",...)
abline(lm(y~x))
par(mar=c(0,3,1,1))
barplot(xhist$counts, axes=FALSE, ylim=c(0, top), space=0,col=gray(.95))
par(mar=c(3,0,1,1))
barplot(yhist$counts, axes=FALSE, xlim=c(0, top),
space=0,col=gray(.95), horiz=TRUE)
par(def.par)}
Sesión 2 – Importación y análisis de datos en R
> scatterplot(datos$TIIE,datos$CETES)
◾Agrupa en categorías y visualiza boxplot (Mínimo, Q1, mediana, Q3, Q3+1,5*IQR, outliers):

> x = runif(10) # Valores


> y = c(1, 1, 1, 2, 2, 1, 2, 3, 3, 2) # Categorias
> boxplot(x ~ y)

Identificar puntos en un gráfico


Mostramos un gráfico a partir de unos datos:

> x = runif(100)
> y = runif(100)
> plot(x,y)

A continuación utilizamos ‘identify’ para indicar que queremos localizar 1 punto:


> identify(x, y, n=1) # Hacemos click en el gráfico y nos
devuelve el indice del punto
[1] 56

Para obtener los valores del punto, utilizamos el indice en los vectores usados para el gráfico:
> c(x[56],y[56])
[1] 0.2514029 0.9420260
Identificar la distribución de los datos

Determinadas pruebas estadísticas que podemos hacer implican que los datos se encuentran repartidos probabilísticamente
según una distribución determinada. Por ejemplo, los T-Tests son útiles cuando tenemos datos que siguen una distribución
normal (gaussiana), pero no cuando son uniformes. Por eso es importante conocer que herramientas tenemos para identificar la
potencial distribución que describe mejor a nuestros datos.

Una primera validación podría ser la ejecución de la prueba Shapiro-Wilk que nos permite comprobar si una distribución es
normal (ver sección "Pruebas estadísticas"). Pero también podemos apoyar nuestro análisis en gráficos que nos ayudaran a
identificar o confirmar la distribución. La siguiente función que nos permite visualizar el histograma y densidad de unos datos
conjuntamente con la densidad teórica de una distribución determinada:

hist.density = function(x, FUN=dnorm, ...) {


hist(x, probability=TRUE, breaks=20, col="light blue")
rug(jitter(x, 5))
# Densidad de x
points(density(x), type='l', lwd=3, col='red')
# Densidad teorica de una distribución concreta
f = function(t) {
# t => Graph's X
FUN(t, ... )
}
curve(f, add=T, col="red", lwd=3, lty=2)
}
Probamos a comparar un par de conjuntos de datos contra la distribución normal:

x = rnorm(100) hist.density(x, FUN=dnorm, mean=mean(x), sd=sd(x))


x = rexp(100) hist.density(x, FUN=dnorm, mean=mean(x), sd=sd(x))

Y ahora, contra la exponencial:

x = rnorm(100) hist.density(rnorm(100), FUN=dexp)


x = rexp(100) hist.density(rexp(100), FUN=dexp)
Otra técnica que podemos utilizar es la visualización del Quartil-Quartil plot:

qq = function (y, ylim, quantiles=qnorm,


main = "Q-Q Plot", xlab = "Theoretical Quantiles",
ylab = "Sample Quantiles", plot.it = TRUE, ...)
{
y = y[!is.na(y)]
if (0 == (n = length(y)))
stop("y is empty")
if (missing(ylim))
ylim = range(y)
x = quantiles(ppoints(n))[order(order(y))]
if (plot.it)
plot(x, y, main = main, xlab = xlab, ylab = ylab, ylim = ylim,
...)
# From qqline
y = quantile(y, c(0.25, 0.75))
x = quantiles(c(0.25, 0.75))
slope = diff(y)/diff(x)
int = y[1] - slope * x[1]
abline(int, slope, ...)
invisible(list(x = x, y = y))
}
La anterior función dibujara el QQ plot de los datos actuales y la línea que une el primer y tercer cuartil de los mismos. Las reglas
para interpretar el gráfico son las siguientes:

1.- Si la parte izquierda se encuentra por ENCIMA de la línea => la distribución de los datos es MAYOR en la izquierda que la de la
distribución comparada

2.- Si la parte izquierda se encuentra por DEBAJO de la línea => la distribución de los datos es MENOR en la izquierda que la de la
distribución comparada

3.- Si la parte derecha se encuentra por ENCIMA de la línea => la distribución de los datos es MENOR en la derecha que la de la
distribución comparada

4.- Si la parte derecha se encuentra por DEBAJO de la línea => la distribución de los datos es MAYOR en la derecha que la de la
distribución comparada

Probamos a comparar unos datos contra la distribución uniforme, exponencial y normal:

qq(runif(100), quantiles=qunif) # La linea se solapa con los puntos


qq(runif(100), quantiles=qexp) # Concentraciones diferentes
qq(runif(100), quantiles=qnorm)
# Con id/nombres de filas

> read.table("dataframe1.csv", header = TRUE, sep = ",",row.names = 1)

# Sin id/nombres de filas


("c:/datos/glucosa.txt", header = T)
> read.table("dataframe2.csv", header = TRUE, sep = ",")

> M=read.table("c:/datos/glucosa.csv", header = TRUE, sep = ",")


La asimetría (skewness) es la medida que indica la simetría de la distribución de una variable respecto a la
media aritmética, sin necesidad de hacer la representación gráfica. Los coeficientes de asimetría indican si hay
el mismo número de elementos a la izquierda y a la derecha de la media, como este valor es difícil de conseguir
se tiende a tomar los valores que son cercanos ya sean positivos o negativos (± 0.5)

Existen tres tipos de curva de distribución según su asimetría:

◾Asimetría negativa: la cola de la distribución se alarga para valores inferiores a la media.


◾Simétrica: hay el mismo número de elementos a izquierda y derecha de la media. En este caso, coinciden la
media, la mediana y la moda. La distribución se adapta a la forma de la campana de Gauss, o distribución
normal.
◾Asimetría positiva: la cola de la distribución se alarga para valores superiores a la media.
σ𝑛𝑖=1 𝑥𝑖 − 𝑥ҧ 3
𝐶𝐴𝐹 =
𝑛 𝑆𝑥3

 Si 𝑪𝑨𝑭 <0: la distribución tiene una asimetría negativa y se alarga a valores menores que la media.
◾ Si 𝑪𝑨𝑭 =0: la distribución es simétrica.
◾ Si 𝑪𝑨𝑭 >0: la distribución tiene una asimetría positiva y se alarga a valores mayores que la media.
Existen tres coeficientes de asimetría:

Coeficiente de asimetría de Pearson

El coeficiente de asimetría de Pearson CAP mide la diferencia entre la media y la moda respecto a la dispersión
del conjunto de datos. Este procedimiento, menos usado, se emplea solamente en distribuciones unimodales y
poco asimétricas.
ഥ − 𝑴𝒐 (𝑿)
𝒙
𝑪𝑨𝑷 =
𝑺𝒙
◾ Si 𝑪𝑨𝑷 <0: la distribución tiene una asimetría negativa, puesto que la media es menor que la moda.
◾ Si 𝑪𝑨𝑷 =0: la distribución es simétrica.
◾ Si 𝑪𝑨𝑷 >0: la distribución tiene una asimetría positiva, ya que la media es mayor que la moda.
El coeficiente de asimetría de Bowley toma como referencia los cuartiles para determinar si la distribución es simétrica o no.
Para aplicar este coeficiente, se supone que el comportamiento de la distribución en los extremos es similar. La asimetría de
Bowley es:
𝑄3 + 𝑄1 − 2𝑄2
𝐶𝐴𝐵 =
𝑄3 − 𝑄1

 Si 𝑪𝑨𝑩 <0: la distribución tiene una asimetría negativa, puesto que la distancia de la mediana al primer cuartil es menor
que al tercero.
◾ Si 𝑪𝑨𝑩 =0: la distribución es simétrica, ya que el primer y tercer cuartil están a la misma distancia de la mediana.
◾ Si 𝑪𝑨𝑩 >0: la distribución tiene una asimetría positiva, ya que la distancia de la mediana al tercer cuartil es mayor que al
primero.
La curtosis (o apuntamiento) es una medida de forma que mide cuán escarpada o achatada está una curva o distribución.

Este coeficiente indica la cantidad de datos que hay cercanos a la media, de manera que a mayor grado de curtosis, más
escarpada (o apuntada) será la forma de la curva.

La curtosis se mide promediando la cuarta potencia de la diferencia entre cada elemento del conjunto de datos y la media,
dividido entre la desviación estándar elevado también a la cuarta potencia. El coeficiente de curtosis es:

σ𝑛𝑖=1 𝑥𝑖 − 𝑥ҧ 4
𝐶𝑢𝑟𝑡𝑜𝑠𝑖𝑠 = 𝑔2 = −3
𝑛 𝑆𝑥4
Como este tipo de medida determina el grado de concentración que presentan los valores en la región central de la
distribución.

 Por medio de esta podremos saber si existe una gran concentración de valores - picuda 𝑔2 > 3 que podríamos llamar
leptocúrtica.
 Una concentración normal de los datos 𝑔2 = 3 que se le podría llamar mesocúrtica, al igual que en la asimetría es
bastante difícil encontrar un coeficiente de curtosis igual a (3), por lo que se suelen aceptar los valores cercanos (3 ±
0.5 aprox.).
 En el ultimo caso una baja concentración o aglomeración de datos - aplastada 𝑔2 < 3 que le llamamos platicúrtica.

Si se deseara calcular la asimetría y la curtosis de la variable APPL, habría en primer lugar que instalar y cargar en R, si
no lo está ya, el paquete fBasics. Y a continuación:
> class(precios)
[1] "data.frame"

> attach(precios)

> kurtosis(APPL)
[1] -1.181526
attr(,"method") Ambos coeficientes están calculados a partir de los momentos y, en el
[1] "excess" caso de la curtosis, se le ha restado 3. Se podría concluir que la
distribución es sesgada a la derecha y algo aplastada.
> skewness(APPL)
[1] 0.3786677
attr(,"method")
[1] "moment"
Vamos a obtenemos las tablas de distribución de frecuencias absolutas y relativas de la base de datos precios de la
variable APPL, utilizando la función table como sigue:

Agrupamos en 10
intervalos de clase

> fabs<-table(cut(APPL,breaks=10))
> View(fabs)
> frel<-table(cut(APPL,breaks=10))/1241

> View(frel)
> fabsacum<-cumsum(fabs)

> View(fabsacum)
> frelacum<-cumsum(frel)

> View(frelacum)
Para hacer un histograma simplemente debemos de escribir la siguiente orden:

> hist(APPL,col="blue")
Histogram of APPL

300
250
200
Frequency

150
100
50
0

100 200 300 400 500 600 700

APPL
Para hacer un histograma simplemente debemos de escribir la siguiente orden:

> hist(APPL,prob=T,col="red")

Histogram of APPL

0.0030
Recordemos que con el parámetro prob= T
tenemos las probabilidades de cada intervalo de
clase, mientras que la omisión de esta instrucción
nos dan un recuento de la frecuencia absoluta de

0.0020
cada intervalo.

Density

0.0010
0.0000

100 200 300 400 500 600 700

APPL
El problema es que R por defecto selecciona el número de intervalos de clases siguiendo un método interno llamado
método de Sturges (# 𝒄𝒍𝒂𝒔𝒆𝒔 = 𝟏 + 𝟑. 𝟑𝟐𝟐 ∗ 𝐥𝐨𝐠 𝑵). Para poder utilizar el número de clases que a nosotros nos
interesa más, tenemos que crear un vector con los puntos de corte de las clases. Esto se puede hacer fácilmente
mediante:
> x<-APPL
> n.clases=10
> Puntos = min(x)+(0:n.clases)*(max(x)-min(x))/n.clases
> hist(x, breaks=Puntos) Histogram of x

400
300
Frequency

200
100
0

100 200 300 400 500 600 700

x
Por ejemplo, para 15 intervalos de clases sería:

> n.clases=15
> puntos=min(x)+(0:n.clases)*(max(x)-min(x))/n.clases
> hist(x, breaks=puntos)
Histogram of x

250
200
Frequency

150
100
50
0

100 200 300 400 500 600 700

x
Cuando la distribución de frecuencias de una variable posee valores atípicos la media aritmética de la distribución no es
una medida robusta (no sufre cambios considerables en presencia de valores extremos), en su lugar suele considerarse la
media truncada la cual elimina un porcentaje de valores en los extremos para el cálculo de la media aritmética.

> mean(x,trim=0.25) > mean(x)


[1] 287.281 [1] 310.5625

Media truncada: elimina


el 25% en este caso de
las observaciones más
grandes y más pequeñas
> hist(APPL, prob=T, xlab=‘Intervalod de clase',ylab='probabilidades',main='Histograma de precios de Apple',col="yellow")
> lines(density(APPL,na.rm=T))

La instrucción anterior dibuja una versión suave del


histograma (una estimación de la densidad de
distribución de la variable APPL.
Las “parcelas” color azul separadas por pequeñas franjas
blancas después de los valores de la variable cerca del eje X,
> rug(jitter(APPL),col="blue") permiten la fácil localización de los valores extremos. Por
ejemplo hay un valor significativamente menor que todos
los demás.
> qqnorm(APPL,main='Gráfica QQ Normal de APPL')

> qqnorm(APPL); qqline(APPL, col = 2)

La imagen muestra una gráfica Q-Q obtenidos, la cual


representa los cuantiles de la variable APPL en contra de los
cuantiles teóricos de una distribución normal (línea de color
rojo).
Podemos ver mejor lo anterior al graficar los precios APPL e IBM. Podemos observar un valor menor que todos los demás, las
zonas con parcelas de color azul muestran datos que no varían mucho entre sí. Vea que en el lado derecho los datos están más
dispersos entre sí y es por ello que las parcelas azules son de menor longitud.
> boxplot(APPL, ylab = "Precios acciones APPL")

> rug(jitter(IBM), side = 2)


remover valores perdidos Tipo de línea

> abline(h = mean(APPL, na.rm = T), lty = 2)


La primera instrucción dibuja un diagrama de caja de variable APPL. Los diagramas de caja proporcionan un resumen rápido
de algunas de las propiedades clave de la distribución de la variable. Es decir, hay una caja cuyos límites verticales son el
primer y tercer cuartiles de la variable. Este rectángulo tiene una línea horizontal en el interior que representa el valor de la
mediana de la variable. Sea 𝑹𝒊𝒒 el rango intercuartil (𝑄3 − 𝑄1 ). La pequeña raya horizontal por encima de la caja es la
observación más grande que es menor o igual al tercer cuartil más 1.5 de 𝑹𝒊𝒒 . La línea horizontal pequeña debajo de la caja
es la observación más pequeña que es mayor o igual al primer cuartil menos 1.5 de 𝑹𝒊𝒒 . Los círculos por debajo o por encima
de estos segmentos pequeños representan las observaciones que son extremadamente bajas o altas en comparación con
todos los demás, y se consideran por lo general como los valores extremos. Esto significa que los diagramas de caja nos dan
un montón de información con respecto a no sólo el valor central y dispersión de la variable, sino también sobre los valores
extremos eventuales.

La segunda instrucción se ha descrito antes (la única diferencia puede ser el lugar donde se trazan los datos), mientras que
el tercero utiliza la función abline() para trazar una línea horizontal en la parte media de la variable, que se obtiene
utilizando la función media ().
El Paquete Handbook of Statistical Analyses Using R

 Instalar el paquete HSAUR

 Cargar el paquete en la sesión: > library("HSAUR")

 Cargamos la base de datos con la que vamos a trabajar: > data("Forbes2000", package = "HSAUR")

La lista Forbes 2000 es un ranking de las empresas más grandes del


mundo, medidas por ventas, utilidades, activos y valor de mercado.
Sólo contiene empresas cotizadas en bolsa.

> print(Forbes2000)
category sales profits assets marketvalue
1
2
Banking 94.71 17.85 1264.03 255.30
Conglomerates 134.19 15.59 626.93 328.54
> View(Forbes2000)
3 Insurance 76.66 6.46 647.66 194.87
4 Oil & gas operations 222.88 20.96 166.99 277.02
5 Oil & gas operations 232.57 10.27 177.57 173.54
6 Banking 49.01 10.81 736.45 117.55
7 Banking 44.33 6.66 757.60 177.96
8 Consumer durables 135.82 7.99 171.71 115.40
9 Diversified financials 53.13 6.48 1019.17 76.84
10 Retailing 256.33 9.05 104.91 243.74
11 Diversified financials 48.95 5.15 853.23 85.07
12 Diversified financials 94.72 4.73 752.49 54.59
13 Oil & gas operations 133.50 8.40 100.72 163.45
14 Insurance 56.22 6.95 172.24 141.14
15 Banking 44.39 4.47 792.70 81.94
16 Technology hardware & equipment 89.13 7.58 104.46 171.54
17 Oil & gas operations 131.64 8.84 87.84 116.64
18 Banking 47.74 4.73 745.09 59.29
19 Banking 35.65 4.95 663.45 90.21
20 Diversified financials 46.26 10.09 752.25 44.25
21 Consumer durables 157.13 5.12 195.58 47.43
22 Food drink & tobacco 60.70 9.20 96.18 111.02
23 Oil & gas operations 112.94 7.43 82.36 92.49
24 Drugs & biotechnology 40.36 6.20 120.06 285.27
25 Banking 31.80 6.20 387.80 97.53
26 Telecommunications services 67.75 2.57 165.97 103.97
27 Banking 33.69 4.90 791.54 61.33
28 Diversified financials 33.00 3.64 580.63 64.81
29 Consumer durables 185.52 3.82 450.00 27.47
> View(Forbes2000)
> class(Forbes2000)
[1] "data.frame“

> length(levels(Forbes2000$country))
[1] 61

> length(levels(Forbes2000$category))
[1] 27

Si deseamos información más detallada:

> str(Forbes2000)
'data.frame': 2000 obs. of 8 variables:
$ rank : int 1 2 3 4 5 6 7 8 9 10 ...
$ name : chr "Citigroup" "General Electric" "American Intl Group" "ExxonMobil" ...
$ country : Factor w/ 61 levels "Africa","Australia",..: 60 60 60 60 56 60 56 28 60 60 ...
$ category : Factor w/ 27 levels "Aerospace & defense",..: 2 6 16 19 19 2 2 8 9 20 ...
$ sales : num 94.7 134.2 76.7 222.9 232.6 ...
$ profits : num 17.85 15.59 6.46 20.96 10.27 ...
$ assets : num 1264 627 648 167 178 ...
$ marketvalue: num 255 329 195 277 174 ...
La salida de la función str nos dice que Forbes 2000 es un objeto de la clase data.frame, que es la estructura de los datos
más importante para el manejo estadísticos en forma tabular en R. Como era de esperar, se almacenan en este objeto la
información sobre 2000 observaciones, es decir, las empresas. Para cada observación están disponibles, los siguientes ocho
variables :

Rango: la clasificación de la empresa.


Nombre: el nombre de la empresa.
País: el país de la empresa.
Categoría: describe los productos que la empresa produce.
Ventas: la cantidad de ventas de la empresa en billones de dólares estadounidenses.
Beneficios: los beneficios de la empresa en billones de dólares estadounidenses.
Activos: los activos de la empresa en billones de dólares.
Valor de mercado: el valor de mercado de la empresa en billones de dólares.
> dim(Forbes2000)
[1] 2000 8
> nrow(Forbes2000)
[1] 2000
> ncol(Forbes2000)
[1] 8
> names(Forbes2000)
[1] "rank" "name" "country" "category" "sales" "profits"
[7] "assets" "marketvalue"
> class(Forbes2000[, "rank"])
[1] "integer"
> class(Forbes2000[, "name"])
[1] "character"

Los corchetes [ ] en las últimas dos instrucciones indican siempre un subconjunto de un objeto más grande o que
seleccione una variable del marco de datos, en nuestro caso solo hemos extraído una variable de toda la tabla. Al ser un
data.frames tienen dos dimensiones, observaciones y variables, se requiere de la coma con el fin de especificar que
queremos un subconjunto de la segunda dimensión, es decir, de las columnas o variables.
> Forbes2000[, "name"][1] > Forbes2000$name[1]
[1] "Citigroup" [1] "Citigroup"

Debido a que las empresas están clasificadas, Citigroup es la compañía más grande del mundo según la lista Forbes 2000.

> class(Forbes2000[, "category"])


[1] "factor"

La clase de objetos “factor” y “caracter” básicamente difieren sólo en la manera en que sus valores se almacenan
internamente. Cada elemento de un vector de clase caracter se almacena como una letra, un conjunto de símbolos o nombres
mientras los factores son variable que no podemos controlar que además contiene números enteros que indica el nivel o
tratamiento del factor. > is.character(Forbes2000[,"rank"])
[1] FALSE
> is.character(Forbes2000[,"name"])
[1] TRUE
> is.character(Forbes2000[,"country"])
[1] FALSE
> is.character(Forbes2000[,"sales"])
[1] FALSE
> is.character(Forbes2000[,"category"])
[1] FALSE
> is.character(Forbes2000[,"profits"])
[1] FALSE
> is.character(Forbes2000[,"assets"])
[1] FALSE
> is.character(Forbes2000[,"marketvalue"])
[1] FALSE
En nuestro caso, hay
> nlevels(Forbes2000[, "category"])
[1] 27

diferentes niveles, es decir, categorías de negocios, que pueden ser extraídos por

> levels(Forbes2000[, "category"])

[1] "Aerospace & defense" "Banking"


[3] "Business services & supplies" "Capital goods"
[5] "Chemicals" "Conglomerates"
[7] "Construction" "Consumer durables"
[9] "Diversified financials" "Drugs & biotechnology"
[11] "Food drink & tobacco" "Food markets"
[13] "Health care equipment & services" "Hotels restaurants & leisure"
[15] "Household & personal products" "Insurance"
[17] "Materials" "Media"
[19] "Oil & gas operations" "Retailing"
[21] "Semiconductors" "Software & services"
[23] "Technology hardware & equipment" "Telecommunications services"
[25] "Trading companies" "Transportation"
[27] "Utilities"
> nlevels(Forbes2000[, "country"])
[1] 61
> levels(Forbes2000[, "country"])
[1] "Africa" "Australia"
[3] "Australia/ United Kingdom" "Austria"
[5] "Bahamas" "Belgium"
[7] "Bermuda" "Brazil"
[9] "Canada" "Cayman Islands"
[11] "Chile" "China"
[13] "Czech Republic" "Denmark"
[15] "Finland" "France"
[17] "France/ United Kingdom" "Germany"
[19] "Greece" "Hong Kong/China"
[21] "Hungary" "India"
[23] "Indonesia" "Ireland"
[25] "Islands" "Israel"
[27] "Italy" "Japan"
[29] "Jordan" "Kong/China"
[31] "Korea" "Liberia"
[33] "Luxembourg" "Malaysia"
[35] "Mexico" "Netherlands"
[37] "Netherlands/ United Kingdom" "New Zealand"
[39] "Norway" "Pakistan"
[41] "Panama/ United Kingdom" "Peru"
[43] "Philippines" "Poland"
[45] "Portugal" "Russia"
[47] "Singapore" "South Africa"
[49] "South Korea" "Spain"
[51] "Sweden" "Switzerland"
[53] "Taiwan" "Thailand"
[55] "Turkey" "United Kingdom"
[57] "United Kingdom/ Australia" "United Kingdom/ Netherlands"
[59] "United Kingdom/ South Africa" "United States"
[61] "Venezuela"
> nlevels(Forbes2000[, "names"])
Error in `[.data.frame`(Forbes2000, , "names") :
undefined columns selected

Si queremos el número de empresas del factor - categoría escribimos: > table(Forbes2000[, "category"])

Aerospace & defense Banking


19 313
Business services & supplies Capital goods
70 53
Chemicals Conglomerates
50 31
Construction Consumer durables
79 74
Diversified financials Drugs & biotechnology
158 45
Food drink & tobacco Food markets
83 33
Health care equipment & services Hotels restaurants & leisure
65 37
Household & personal products Insurance
44 112
Materials Media
97 61
Oil & gas operations Retailing
90 88
Semiconductors Software & services
26 31
Technology hardware & equipment Telecommunications services
59 67
Trading companies Transportation
25 80
Utilities
110
Las variables ventas, activos, ganancias y valor de mercado son de tipo numérico, propias para mediciones continuas o
discretas, por ejemplo

> class(Forbes2000[, "sales"])


[1] "numeric"

Un resumen de los estadísticas más comunes como la media, mediana y el rango pueden ser encontrados:

> summary(Forbes2000[, "sales"])


Min. 1st Qu. Median Mean 3rd Qu. Max.
0.010 2.018 4.365 9.697 9.548 256.300

La base de datos Forbes2000 contiene tres tipos de variables.


 FACTORES o variables cualitativas: país y categoría
 NUMÉRICAS: rango, ventas, utilidades, activos y valor de mercado
 CARACTERES: nombre
Los ejemplos mostrados en la sección anterior han ilustrado la importancia de los data.frames para almacenar y manejar
datos tabulares en R. Internamente, un data.frame es una lista de vectores de una longitud n común, el número de filas de
la tabla. Cada uno de esos vectores representa las mediciones de una variable y hemos visto que podemos acceder a una
variable por su nombre, por ejemplo, los nombres de las empresas.

> empresas <- Forbes2000[, "name"] > empresas<- Forbes2000$name

Por supuesto, el vector de las empresas es de la clase caracter y de longitud 2000. Un subconjunto de los elementos de las
vector “empresa” puede ser extraído utilizando el operador subconjunto [ ]. Por ejemplo, la primera de las empresas de las
2000 que figuran en la lista Forbes 2000 es

> empresas[1]
[1] "Citigroup"

Y las tres primeras empresas:

> empresas[1:3]
[1] "Citigroup" "General Electric" "American Intl Group"
O bien, por ejemplo todas las empresas, excepto aquellos con números de cuatro a dos mil, es decir, las tres principales
empresas, son de nuevo:

> empresas[-(4:2000)]
[1] "Citigroup" "General Electric" "American Intl Group"

La información completa acerca de las tres primeras empresas se puede imprimir de una manera similar. Co es un
data.frames tienen un concepto de filas y columnas, tenemos que separar los subconjuntos correspondientes a las filas
y columnas MEDIANTE una coma. La declaración

> Forbes2000[1:3, c("name", "sales", "profits", "assets")]


name sales profits assets
1 Citigroup 94.71 17.85 1264.03
2 General Electric 134.19 15.59 626.93
3 American Intl Group 76.66 6.46 647.66
Podríamos estar interesados en la extracción de las empresas más grandes con respecto a un orden alternativo. Las tres
principales compañías en cuanto a ventas, pueden calcularse a lo largo de las siguientes instrucciones. En primer lugar,
tenemos que calcular el orden de las ventas de las empresas.

> orden.ventas <- order(Forbes2000$sales)

Ordena de menor mayor

que devuelve los índices o rangos de los elementos ordenados


de menor a mayor con base al vector numérico de ventas. En rangos
consecuencia, las tres empresas con las ventas más bajas son:

> empresas[orden.ventas[1:3]]
[1] "Custodia Holding" "Central European Media" "Minara Resources"
Las tres empresas con las ventas más altas son:

> empresas[orden.ventas[1998:2000]]
[1] "ExxonMobil" "BP" "Wal-Mart Stores"

Si deseamos ver los países asociados a las empresas con mayor ventas:

> pais <- Forbes2000[, "country"]

> View(pais)

> pais[orden.ventas[1998:2000]]
[1] United States United Kingdom United States
61 Levels: Africa Australia Australia/ United Kingdom Austria Bahamas
Belgium ... Venezuela
Los índices de las tres empresas con más ventas son los elementos 1998, 1999 y 2000 del vector con valores enteros
orden.ventas.
Máximo 5 variables

> Forbes2000[orden.ventas[c(2000, 1999, 1998)], c("name","sales", "profits", "assets", "country")]


name sales profits assets country
10 Wal-Mart Stores 256.33 9.05 104.91 United States
5 BP 232.57 10.27 177.57 United Kingdom
4 ExxonMobil 222.88 20.96 166.99 United States

Otra manera de seleccionar elementos de un vector es el uso de un vector lógico siendo TRUE cuando el elemento
correspondiente se debe seleccionar y FALSE en caso contrario.
Las empresas con activos con más de 1000 billones de son:

> Forbes2000[Forbes2000$assets > 1000, c("name", "sales", "profits", "assets")]


name sales profits assets
1 Citigroup 94.71 17.85 1264.03
9 Fannie Mae 53.13 6.48 1019.17
403 Mizuho Financial 24.40 -20.11 1115.90

donde la expresión Forbes 2000 $ activos> 1000 indica un vector lógico de longitud 2000, donde
> table(Forbes2000$assets > 1000)

FALSE TRUE
1997 3

Los elementos son falsos o verdaderos. De hecho, para algunas de las empresas la medición de la variable beneficios se no
existe. En R, los valores perdidos son tratado por un símbolo especial, NA, lo que indica que esta medida no está disponible.
Las observaciones con información no existente se pueden obtener a través de:

> no.beneficios <- is.na(Forbes2000$profits)

> table(no.beneficios)
no.beneficios
FALSE TRUE Note que hemos usado la instrucción table
1995 5

!CUIDADO!
Si escribimos, se desliega una serie de palabras FALSE TRUE…. Que llenará la pantalla

> no.beneficios
Ya que el objetos no.beneficios es una variable de tipo lógico.

> class(no.beneficios)
[1] "logical"

> table(no.beneficios)
no.beneficios
FALSE TRUE
1995 5
> Forbes2000[no.beneficios, c("name", "sales", "profits", "assets","country")]
name sales profits assets country
772 AMP 5.40 NA 42.94 Australia
1085 HHG 5.68 NA 51.65 United Kingdom
1091 NTL 3.50 NA 10.59 United States
1425 US Airways Group 5.50 NA 8.58 United States
1909 Laidlaw International 4.48 NA 3.98 United States
Donde la función is.na devuelve un vector lógico, siendo TRUE cuando el correspondiente elemento del vector es
suministrado NA. Un enfoque más cómoda está disponible cuando queremos eliminar todas las observaciones con al menos
un valor faltante en un objeto data.frame. La función complete.cases en un data.frame devuelve un vector lógico siendo
TRUE cuando la observación correspondiente no contiene ningún valor faltante:

> table(complete.cases(Forbes2000))

FALSE TRUE
5 1995

La función subset toma un data.frame como primer argumento y una expresión lógica como segundo argumento. Por
ejemplo, podemos seleccionar un subconjunto de la lista Forbes 2000 que consta de todas las empresas situadas en
México mediante la instrucción:

> Mexicocomp <- subset(Forbes2000, country == "Mexico")


> dim(Mexicocomp)
[1] 17 8
# de variables

es decir, 17 de las 2000 empresas son Mexicanas. Tenga en cuenta que no es necesario extraer la variable country de la
data.frame de Forbes 2000 cuando formulamos la expresión lógica.
Existen dos funciones útiles para obtener una visión general acerca de los objetos en R: str y sumary, donde str
proporciona una descripción más detallada acerca del tipo de datos y el summary proporciona una resumen de una
colección de estadísticos. Por ejemplo, la aplicación str para el conjunto de datos de Forbes 2000, genera la siguiente
estructura interna:

> str(Forbes2000)
'data.frame': 2000 obs. of 8 variables:
$ rank : int 1 2 3 4 5 6 7 8 9 10 ...
$ name : chr "Citigroup" "General Electric" "American Intl Group" "ExxonMobil" ...
$ country : Factor w/ 61 levels "Africa","Australia",..: 60 60 60 60 56 60 56 28 60 60 ...
$ category : Factor w/ 27 levels "Aerospace & defense",..: 2 6 16 19 19 2 2 8 9 20 ...
$ sales : num 94.7 134.2 76.7 222.9 232.6 ...
$ profits : num 17.85 15.59 6.46 20.96 10.27 ...
$ assets : num 1264 627 648 167 178 ...
$ marketvalue: num 255 329 195 277 174 ...
Por otro lado, con la función summary se obtiene la siguiente salida:

> summary(Forbes2000)

De este resultado podemos ver inmediatamente que la mayoría de las empresas se encuentran
en los EE.UU. y que la mayoría corresponden al sector bancario, así como que las pérdidas,
corresponden aproximadamente hasta 26 billones de dólares. Internamente, summary es una
función genérica con métodos para una multitud de clases, es decir, summary se puede aplicar
a objetos de diferentes clases y reportará resultados sensibles. Aquí, suministramos un objeto
data.frame al summary y es natural aplicar dicho resumen para cada una de las variables de
este data.frame. Debido a que un data.frame es una lista con cada variable igual a un elemento
de la lista.
Un resultado similar, solo que más ordenado por variable se obtiene con la función lappy:

> lapply(Forbes2000, summary)


Los miembros de la familia apply ayudan a resolver tareas recurrentes para cada elemento de un data.frame, matriz, lista o
para cada nivel de un factor. Podría ser interesante comparar los beneficios en cada una de las 27 categorías. Para ello,
primero calculamos la media de las ganancias para cada categoría:

> mediana.ganancias <- tapply(Forbes2000$profits, Forbes2000$category,median, na.rm = TRUE)


Remueve los valores perdidos

Un comando que puede ser leído de la siguiente forma: para cada nivel del factor category , determinar los elementos
correspondientes del vector numérico profits y hallar su mediana con el argumento adicional na.rm =TRUE, éste
último es necesario porque los beneficios contiene valores perdidos que conduciría a un resultado no sensible de la
función de la mediana.
Aerospace & defense Banking
0.260 0.140
Business services & supplies Capital goods
0.160 0.150
Chemicals Conglomerates
0.185 0.270
Construction Consumer durables
0.190 0.225
Diversified financials Drugs & biotechnology
0.200 0.350
Food drink & tobacco Food markets
0.270 0.200
Health care equipment & services Hotels restaurants & leisure
0.230 0.210 > median(Forbes2000$profits)
Household & personal products Insurance [1] NA
0.310 0.220
Materials Media
0.150 0.150
Oil & gas operations Retailing
0.350 0.190
Semiconductors Software & services
0.150 0.240
Technology hardware & equipment Telecommunications services
0.130 0.275
Trading companies Transportation
0.070 0.130
Utilities
0.225
Las tres categorías con mayor mediana en las ganancias se calculan a partir del vector de beneficios ordenados:

en forma inversa Ordena los valores

> rev(sort(mediana.ganancias))[1:3]
Oil & gas operations Drugs & biotechnology Household & personal products
0.35 0.35 0.31

donde rev reorganiza el vector de medianas de las


ganancias ordenándolos de mayor a menor.
Por supuesto, podemos reemplazar la función de la
mediana con media o lo que sea más apropiado al usar
tapply. En nuestra caso, no es una buena opción, ya
que las distribuciones de los beneficios o ventas son
naturalmente sesgadas.

> rev(sort(mediana.ganancias))[25:27]
Transportation Technology hardware & equipment Trading companies
0.13 0.13 0.07
¿ Por qué calcular la mediana en lugar de la media ?

> kurtosis(Forbes2000$profits,na.rm = TRUE)


[1] 73.42632
attr(,"method")
[1] "excess"
> skewness(Forbes2000$profits,na.rm = TRUE)
[1] -1.833375
attr(,"method") Sesgada a la izquierda
[1] "moment"
> mean(Forbes2000$profits,na.rm=TRUE)
[1] 0.3811328
> mean(Forbes2000$profits,na.rm=TRUE,trim=0.15)
[1] 0.2422835
> mean(Forbes2000$profits,na.rm=TRUE,trim=0.25)
[1] 0.2172873
> mean(Forbes2000$profits,na.rm=TRUE,trim=0.30)
[1] 0.2089862
> mean(Forbes2000$profits,na.rm=TRUE,trim=0.35)
[1] 0.2036728
> mean(Forbes2000$profits,na.rm=TRUE,trim=0.40)
[1] 0.199599

> median(Forbes2000$profits,na.rm=TRUE)
[1] 0.2
El grado de asimetría de la distribución puede ser investigado mediante la construcción de histogramas utilizando la
función hist. (Alternativas más sofisticadas, tales como estimadores de densidad suaves se podrán tomar en cuenta más
adelante). En R, las relaciones de regresión son especificadas por la fórmula modelo (model formulae) que, en el caso
bivariado simple, es:

dependiente regresor

> fm <- marketvalue ~ sales

> class(fm)

[1] "formula"
> layout(matrix(1:2, nrow = 2)) Construimos una pantalla gráfica de 2x1

> hist(Forbes2000$marketvalue) Crea el primer histograma con la variable valor de mercado

> hist(log(Forbes2000$marketvalue)) Grafica un segundo histograma con el logaritmo del valor de mercado
con la variable dependiente en el lado izquierdo y la variable independiente en el lado derecho. La tilde separa la parte
izquierda y derecha. Debido a que las distribuciones de ambos el valor de mercado y las ventas están sesgadas elegimos para
su representación sus logaritmos. Un diagrama de dispersión de los 2000 datos en bruto es poco informativo debida a ciertas
áreas con muy alta densidad. Como las distribuciones tanto del valor de mercado y las ventas están sesgadas elegimos para
su representación sus logaritmos.

> plot(log(marketvalue) ~ log(sales), data = Forbes2000,pch = ".")

Gráfico de dispersión de los logaritmos del valor de mercado y las ventas.


> plot(log(marketvalue)~log(sales),data=Forbes2000,col=rgb(0.5,0.5,0.2,0.1),pch=16)

Gráfica con sombreado transparente


Si la variable independiente es un factor, una representación mediante un diagrama de caja es una elección natural. Ya que,
por ejemplo para cuatro países seleccionados, las distribuciones de los logaritmos del valor de mercado se pueden comparar
visualmente. Aquí, el ancho de las cajas son proporcionales a la raíz cuadrada del número de empresas de cada país y como
ya sabemos los valores de mercado extremadamente grandes o pequeñas son representado por puntos individuales.

> boxplot(log(marketvalue) ~ country, data = subset(Forbes2000,country %in% c("United Kingdom",


"Germany","India", "Mexico")), ylab = "log(marketvalue)",varwidth = TRUE)
4
log(marketvalue)

2
0
-2

Africa Bahamas Canada Denmark Greece India Islands Jordan Malaysia Norway Peru Russia Spain Thailand United States
> iqr <- function(x, ...) {
q <- quantile(x, prob = c(0.25, 0.75),
names = FALSE,
...)
return(diff(q))
}

> iqr(Forbes2000$profits, na.rm = TRUE)


[1] 0.36
Puesto que no hay diferencia entre las funciones que se han escrito por los desarrolladores de R y las funciones creadas por
nosotros como usuarios, se puede calcular el rango intercuartil de los profits de cada una de las category de negocios
mediante el uso de nuestra función iqr dentro de la sentencia lapply.

> iqr.beneficios <- tapply(Forbes2000$profits, Forbes2000$category, iqr, na.rm = TRUE)

> iqr.beneficios
> iqr.beneficios1 <- tapply(Forbes2000$profits, Forbes2000$country, iqr, na.rm = TRUE)

> iqr.beneficios1
Podemos extraer las categorías con la variabilidad más pequeña y más grande.

> levels(Forbes2000$category)[which.min(iqr.beneficios)]
[1] "Hotels restaurants & leisure"

> levels(Forbes2000$category)[which.max(iqr.beneficios)]
[1] "Drugs & biotechnology"

Observamos que las variables que generan menos beneficios son las empresas turísticas en comparación
con las ganancias de la industria farmacéutica.
Como caso práctico para analizar la relación entre atributos se ha elegido el archivo de datos titanic.dat, en el que
aparecen las variables Class, Sex, Age y Survived, que aportan información, respectivamente, sobre la clase que
ocupaba el pasajero, su sexo, edad y si sobrevivió o no al famoso naufragio.

> data(Titanic)

> View(Titanic)

Variable 1: clase
> class(Titanic) Variable 2: género
[1] "table" Variable 3: edad
Variable 4: sobrevivir
> ftable(Titanic, row.vars = 1:3)

Survived No Yes
Class Sex Age
1st Male Child 0 5
Adult 118 57
Female Child 0 1
Adult 4 140
2nd Male Child 0 11
Adult 154 14 Coloca las 3 primeras variables en filas, y la cuarta
Female Child 0 13 variable Survived aparece como columna.
Adult 13 80
3rd Male Child 35 13
Adult 387 75
Female Child 17 14
Adult 89 76
Crew Male Child 0 0
Adult 670 192
Female Child 0 0
Adult 3 20
> ftable(Titanic, row.vars = 1:2, col.vars = "Survived")
Survived No Yes
Class Sex
1st Male 118 62
Female 4 141
2nd Male 154 25
Female 13 93
3rd Male 422 88
Female 106 90
Crew Male 670 192
Female 3 20

Reagrupa o colapsa una variable. Tabla marginal


con solo 3 variables. Dos en filas y una en columnas.
> ftable(Titanic, row.vars = "Survived", col.vars = 1)
Class 1st 2nd 3rd Crew
Survived
No 122 167 528 673
Yes 203 118 178 212

Hallamos la tabla en porcentajes

> Tabla1<-prop.table(Tabla)
> Tabla1
Class 1st 2nd 3rd Crew
Survived
No 0.05542935 0.07587460 0.23989096 0.30577010
Yes 0.09223080 0.05361199 0.08087233 0.09631985
Prueba de hipótesis para determinar independencia entre atributos.

> Prueba <- chisq.test(Tabla,correct=TRUE)


> Prueba

Pearson's Chi-squared test

data: Tabla
X-squared = 190.4, df = 3, p-value < 2.2e-16

Usos de la distribución Ji-Cuadrada:

• Determinar si existen diferencias significativas entre las proporciones muestrales de dos variables.
• Para determinar si los atributos de dos variables son o no independientes.

𝐻0 = 𝑙𝑎𝑠 𝑣𝑎𝑟𝑖𝑎𝑏𝑙𝑒𝑠 𝑠𝑜𝑛 𝑖𝑛𝑑𝑒𝑝𝑒𝑛𝑑𝑖𝑒𝑛𝑡𝑒𝑠

𝐻1 = 𝑙𝑎𝑠 𝑣𝑎𝑟𝑖𝑎𝑏𝑙𝑒𝑠 𝑠𝑜𝑛 𝑑𝑒𝑝𝑒𝑛𝑑𝑖𝑒𝑛𝑡𝑒𝑠

𝑁𝑖𝑣𝑒𝑙 𝑑𝑒 𝑠𝑖𝑔𝑛𝑖𝑓𝑖𝑐𝑎𝑛𝑐𝑖𝑎 = 𝛼
𝑆𝑖 𝜒 2 = 0, indicaría una ausencia de relación y a medida que𝜒 2 crece la
relación va en aumento.

El estadístico 𝜒 2 no está acotado en un rango de valores que permita interpretar la intensidad de la relación, por lo que se
debe recurrir a algún coeficiente derivado que esté acotado. Los más usuales son el coeficiente de contingencia y el
coeficiente de Cramer, ambos en el intervalo [0, 1). Se empleará en este caso el primero que viene dado por:

𝜒2
𝐶=
𝜒2 + 𝑛

donde n es el tamaño de la muestra. En nuestro caso el coeficiente de contingencia vale 0.28, lo que indica una cierta
relación entre ambos atributos. Si se observa la tabla de doble entrada se ve que porcentualmente se salvaron más
pasajeros de primera clase, mientras que los de tercera clase y la tripulación fueron los que más sufrieron las
consecuencias del naufragio.
Nota sobre la el p-value:

1.- Si el valor p es > a entonces NO SE RECHAZA H0, donde a es el nivel de significancia de la prueba.
2.- Si el valor p es < a entonces SE RECHAZA H0, con a el nivel de significancia de la prueba de hipótesis.

Interpretación: Siendo la hipótesis nula que la población está distribuida normalmente, si el valor-p es menor a
alfa (nivel de confianza) entonces la hipótesis nula es rechazada (se concluye que los datos no vienen de una
distribución normal). Si el valor-p es mayor a alfa, no se rechaza la hipótesis y se concluye que los datos siguen
una distribución normal.

barplot(Tabla, xlab=“Clase”, ylab=“Frecuencia”, legend.text=c(“No superviviente”, “Superviviente”), beside=TRUE,col=cm.colors(2))


barplot(Tabla, xlab=“Clase”, ylab=“Frecuencia”, legend.text=c(“No
superviviente”, “Superviviente”), beside=TRUE,col=cm.colors(2))
> barplot(Tabla, xlab="Clase", ylab="Frecuencia", legend.text=c("No
superviviente", "Superviviente"), beside=TRUE,col=cm.colors(2))
> barplot(Tabla1, xlab="Clase", ylab="Frecuencia", legend.text=c("No superviviente",
"Superviviente"), beside=TRUE,col=cm.colors(2))
> mosaicplot(Titanic, main="Supervivientes del Titanic", color=c("red", "green"))

Se han seleccionado los colores verde para los supervivientes y rojo para los no supervivientes.
> mosaicplot(Titanic, main="Supervivientes del
Titanic", color=c("red", "green"))
> x = read.table("c:/datos/peso_altura.dat", header = T)

Para ilustrar los conceptos sobre el ajuste lineal se procederá a analizar la relación entre peso y altura del
archivo de datos peso_altura.dat, en el que aparecen, entre otras variables, el sexo, peso y altura de un grupo
de personas. Dado que se trata de un ejemplo y que no se cuenta con elementos adicionales para avalar la
decisión, se decide explicar el peso en función de la altura.

> hist(x$ALTURA, scale="frequency", breaks=seq(155,200,3), col=heat.colors(13))


> hist(x$PESO, scale="frequency", breaks=seq(55,110,5), col=heat.colors(13))

Una primera visión de los histogramas permite detectar una


bimodalidad tanto en la variable peso como en la altura,
aunque ello es un indicio claro de mezcla de poblaciones, se
continuará con los siguientes pasos del ajuste con todos los
datos, en un ejercicio básicamente didáctico, en busca de
establecer la relación que justifique el peso en función de la
altura.
> cor.test(x$ALTURA, x$PESO, alternative="two.sided", method="pearson")

Pearson's product-moment correlation

data: x$ALTURA and x$PESO


t = 15.84, df = 98, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
0.7818060 0.8952982
sample estimates:
cor
0.8480039

El coeficiente de correlación es positivo y relativamente alto, r = 0, 848, lo que indica que existe relación directa entre
las variables. En cuanto a la intensidad, el coeficiente de determinación 𝑅2 = 𝑟 2 = 0.719 implica que un 28% de la
variación de Y no se explica por X a través de la recta de ajuste.
> Regresion <- lm(x$PESO~x$ALTURA)
> Regresion

Call:
lm(formula = x$PESO ~ x$ALTURA)

Coefficients:
(Intercept) x$ALTURA
-188.977 1.528
> summary(Regresion)

Call:
lm(formula = x$PESO ~ x$ALTURA)

Residuals:
Min 1Q Median 3Q Max
-18.120 -4.214 1.352 4.758 15.272

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -188.97703 16.82888 -11.23 <2e-16 ***
x$ALTURA 1.52801 0.09647 15.84 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 6.758 on 98 degrees of freedom


Multiple R-squared: 0.7191, Adjusted R-squared: 0.7162
F-statistic: 250.9 on 1 and 98 DF, p-value: < 2.2e-16

También podría gustarte