2014-10-11

Ley de Benford en R

Title La ley de Benford, también conocida como la ley del primer dígito, se refiere a la frecuencia de distribución del primer dígito en muchos de los números que aparecen en la vida real. En esta distribución, el 1 aparece con una frecuencia aproximada del 30% mientras que el 9 aparece con una frecuencia menor del 5%. Por primer dígito se refiere al primer dígito no nulo o significativo.

Esta ley se puede aplicar a una gran variedad de fuentes de datos: facturas de electricidad, direcciones de calles, precios de acciones, cifras de población, tasas de mortalidad, longitud de los ríos o constantes físicas y matemáticas. Se ha aplicado en la detección de fraudes en contabilidad, resultados electorales y científicos.

Distribución

En R, al igual que hicimos en Excel, podemos calcular la tabla con la probabilidad para cada dígito. En R, al contrario de Excel, log calcula por defecto el logaritmo natural. Para calcular el logaritmo en base 10, necesitamos especificar la base o usar la función log10.

benford <- log10(1+1/(1:9)) # O log(1+1/(1:9), base = 10)
data.frame(benford)
     benford
1 0.30103000
2 0.17609126
3 0.12493874
4 0.09691001
5 0.07918125
6 0.06694679
7 0.05799195
8 0.05115252
9 0.04575749 
sum(benford) # Comprobamos que suma 1
[1] 1

Gráficos

Si representamos el vector sin ningún tipo de argumento, obtenemos el siguiente gráfico de barras.

barplot(benford)
Buscamos un formato similar al creado en la entrada ley de Benford en Excel. Formateamos el gráfico suministrando los argumentos necesarios.

barplot(rev(benford*100), # Revierte el orden
        las = 1, # Etiquetas del eje horizontales 
        main = "Ley de Benford",
        xlab = "%",
        ylab = "Dígitos",
        names.arg = c(9:1), # Dígitos orden inverso 
        horiz = TRUE,       # Barras horizontales
        col = "steelblue", 
        border = "white", 
        xlim = c(0, 35))    # Amplia el máximo de la escala                                                                                          
grid(ny = 0) # Líneas de división

Referencias:

?log
?barplot
Bendford's law, mathematical statement
Benford law and lognormal distributions

Entradas relacionadas:
Ley de Benford en Excel
Distribución de frecuencias en Ms Excel

2014-10-09

Sustituir vocales en Excel mediante VBA

Title Para sustituir las vocales de una cadena de texto, en lugar de la función sustituir anidada, podemos crear una función definida por el usuario.

Modificamos una función usada previamente para reemplazar cadenas de texto.

Public Function ReemplazarVocales(Reemplazarcadena As String) As String

Dim Originales As Variant, Sustituciones As Variant
Dim i As Long
Originales = Array("a", "e", "i", "o", "u")
Sustituciones = Array("", "", "", "", "")
ReemplazarVocales = Reemplazarcadena
    For i = 0 To 4 'Los subíndices de matriz empiezan en 0,
                   'por tanto Originales(0) = "a"[...] Originales(4)="u"
    ReemplazarVocales = Replace(ReemplazarVocales, Originales(i), Sustituciones(i), _
    compare:=vbTextCompare) 'Comparación textual
    Next
End Function
En este caso, al contrario que con la función Sustituir con la función Replace podemos especificar que la comparación sea textual, vbTextCompare, y así no sea sensible a las mayúsculas o minúsculas. Si omitimos dicho argumento, o escribimos vbBinaryCompare, la comparación será binaria y sensible a las mayúsculas o minúsculas.

Entradas relacionadas:
Sustituir vocales en Excel mediante fórmulas

Referencias:
Replace (Función, Visual Basic)

2014-10-07

Superponer gráficos en R: distribución normal

Title Para superponer gráficos con R empleamos la función curve y su argumento add. Creamos una curva inicial en la que especificamos los argumentos del gráfico base, y le superponemos el resto de curvas.

El objetivo es obtener unos gráficos similares a los de la Wikipedia:

Función de densidad de probabilidad

# Creamos la curva inicial
curve(dnorm(x, 0, sqrt(0.2)), # Función dnorm a evaluar
      -5, 5, 1000, # Límites de x y nº de valores a evaluar
      col = "red", 
      las = 1, # Etiquetas alineadas horizontalmente
      ann = FALSE, # Sin títulos en los ejes
      xaxp = c(-5, 5, 10),  # Marcas del eje x
      ylim = c(0,1), # Límites del eje
      yaxs = "i") # Estilo del eje y, ajustado a los límites
# Añadimos el resto de curvas
curve(dnorm(x), add = TRUE, col = "green")
curve(dnorm(x, 0, sqrt(5)), add = TRUE, col = "blue")
curve(dnorm(x, -2, sqrt(0.5)), add = TRUE, col = "pink")
Le añadimos la leyenda con las letras griegas: μ (mi, mu en inglés) y σ (sigma).

# Lista (expression vector) con los textos de la leyenda
l <- expression(paste(mu, "= 0, ", sigma^2, "= 0.2"), paste(mu, "= 0, ", sigma^2, "= 1.0"), paste(mu, "= 0, ", sigma^2, "= 5.0"), paste(mu, "=-2, ", sigma^2, "= 0.5"))
legend("topright",          # Posición
       legend = l,          # Expression vector anterior
       lty = c(1, 1, 1, 1), # Líneas sólidas
       bty = "n",           # Sin bordes
       col = c("red", "green", "blue", "pink"),
       inset = .05,         # Espaciado del margen
       y.intersp = .75)     # Interlineado
# Para añadir líneas de división
grid()
En este segundo gráfico he eliminado el último argumento en la curva inicial (yaxs = "i") para que el eje de abscisas no corte con el de ordenadas en 0. Y añadí las líneas de división

Función de distribución acumulada de probabilidad

# Curvas
curve(pnorm(x, 0, sqrt(0.2)), -5, 5, col = "red", las = 1, ann = F, 
      xaxp = c(-5, 5, 10))
curve(pnorm(x),add = TRUE, col = "green")
curve(pnorm(x, 0, sqrt(5)), add = TRUE, col = "blue")
curve(pnorm(x, -2, sqrt(0.5)), add = TRUE, col = "pink")
# Leyenda
l <- expression(paste(mu, "= 0, ", sigma^2, "= 0.2"), paste(mu, "= 0, ", sigma^2, "= 1.0"), paste(mu, "= 0, ", sigma^2, "= 5.0"), paste(mu, "=-2, ", sigma^2, "= 0.5"))
legend("bottomright", legend = l, lty = c(1, 1, 1, 1), bty = "n", col = c("red", "green", "blue", "pink"), inset = .05, y.intersp = .75)
grid()

Referencias

2014-10-05

Sustituir vocales en Excel mediante fórmulas

Title El objetivo es eliminar las vocales de una cadena de texto. Partir de la columna Palabras y llegar a las columnas Minúsculas y Mayúsculas.

1. Partimos de la fórmula Sustituir.

=SUSTITUIR(A2;"a";"")
2. Como es sensible al uso de las mayúsculas, convertimos previamente las letras de la cadena de texto a minúsculas. Así sustituirá tanto las a, e, i, o y u como las A, E, I, O y U.

=SUSTITUIR(MINUSC(A2);"a";"")
Si queremos el resultado en mayúsculas, hacemos lo contrario.

=SUSTITUIR(MAYUSC(A2);"A";"")
3. Encadenamos tantas veces la función como el número de letras a sustituir, 5.

=SUSTITUIR(SUSTITUIR(SUSTITUIR(SUSTITUIR(SUSTITUIR(MINUSC(A2);"a";"");"e";"");"i";"");"o";"");"u";"")
Si queremos el resultado en mayúsculas, hacemos lo contrario.

=SUSTITUIR(SUSTITUIR(SUSTITUIR(SUSTITUIR(SUSTITUIR(MAYUSC(A2);"A";"");"E";"");"I";"");"O";"");"U";"")

2014-10-02

Enviar objeto de Access por correo electrónico

Title En Ms Access con la acción SendObject (enviar objeto) podemos enviar objetos de la base de datos por correo electrónico: tablas, consultas, informes, formularios o módulos.

Macro

En la macro en Vista Diseño seleccionamos dicha acción y completamos los argumentos correspondientes:

2007

2010-13

Los argumentos de la macro tienen un límite de 255 caracteres en todas las versiones. Una limitación importante en el caso del texto del mensaje y de los destinatarios (Para, Cc, Cco). Si queremos sortearla, creamos el código en VBA (en el apartado siguiente) o guardamos la macro como código VBA y lo editamos.

VBA

En Visual Basic, la sintaxis es:

DoCmd.SendObject(ObjectType, ObjectName, OutputFormat, To, Cc, Bcc, Subject, MessageText, EditMessage, TemplateFile)

Si dejamos todos los argumentos en blanco, nos abrirá un correo electrónico sin mensaje u objeto adjunto.

DoCmd.SendObject 
Si completamos el tipo de objeto y el nombre del mismo, pero dejamos en blanco el formato de resultados, nos preguntará por el mismo al ejecutar el código.

DoCmd.SendObject acQuery, "Consulta1"
Para sobrepasar el límite de los 255 caracteres escribimos el texto correspondiente en cada argumento rodeado de comillas. Para dividir una cadena de texto demasiado larga en mitad de un argumento, cerramos las comillas y usamos el carácter & seguido de _. La continuación del argumento irá entrecomillada también, como en el siguiente ejemplo:

Sub EnviarObjeto()
DoCmd.SendObject acTable, "Tabla1", acFormatXLS, "usuario1@destino.com; usuario2@destino.com;" & _
"usuario3@destino.com"
End Sub

Referencias:
Método DoCmd.SendObject (Access)

2014-09-29

Gráfico de la función de distribución acumulada de la distribución normal en R

Title En R, vamos a crear el gráfico de la función de distribución de la distribución normal usando tres funciones: plot, curve y plot.ecdf. En esta entrada anterior vimos el gráfico de la función de densidad de la distribución normal.

Función plot

Creamos un vector con las coordenadas x, en los argumentos de seq (secuencia) especificamos los límites y el número de valores intermedios o el incremento. En las coordenadas y, la función de distribución pnorm, por defecto una distribución normal estándar, N(0, 1), con una media de 0 y una varianza de 1.

x <- seq(-3, 3, 0.001) # Incremento de la secuencia: 6001 valores
# O bien
x <- seq(-3, 3, length = 1000) # 1000 valores intermedios

Usamos la función plot:

plot(x,          # Coordenadas x
     pnorm(x),   # Coordenadas y
     type = "l", # Tipo de gráfico líneas
     las = 1)    # Etiquetas alineadas horizontalmente

Función curve

No es necesario crear un vector con las coordinadas x. Solamente especificar el nombre de la función que evaluará: pnorm. Por defecto, curve evalua 101 valores (n = 101).

curve(pnorm(x), xlim = c(-3, 3), las = 1)

Función ecdf

La función ecdf, empirical cumulative distribution function, computa la distribución acumulada. Y plot.ecdf implementa el método plot para representarla gráficamente.

plot.ecdf(rnorm(10000)) # O más intrincadamente
plot(ecdf(rnorm(10000)))

plot.ecdf(rnorm(10000), 
xlim = c(-3, 3), # Extremos del eje x
las = 1) # Etiquetas alineadas horizontalmente

Más ejemplos

Dos ejemplos con distribuciones distintas de la distribución normal estándar. En este caso, sí es necesario suministrar los argumentos media y desviación típica (raíz cuadrada de la varianza). Añadimos el parámetro xaxp para forzar el número de marcas del eje x entre las dos coordinadas de los extremos.

N(-2, 0.5)

x <- seq(-5, 5, 0.001)
plot(x, pnorm(x, -2, sqrt(.5)), type = "l", las = 1, xaxp =c(-5, 5, 10))
N(0, 0.2)

curve(pnorm(x, 0, sqrt(.2)), -5, 5, las = 1, 
xaxp = c(-5, 5, 10))
Referencias:

2014-09-26

Importar HTML en R: Películas más taquilleras IMDb

Title Continuamos practicando la importación de tablas HTML en R. En el siguiente ejemplo importamos los resultados de las películas más taquilleras.

Importación

library(XML) # Función readHTMLTable
library(reshape2) # Función colsplit
url <- "http://www.imdb.com/chart"
peliculas <- readHTMLTable(url, which = 1, stringsAsFactors = FALSE)

Manipulación

peliculas <- transform(peliculas, peliculas = colsplit(peliculas[[2]], pattern = "\n", names = c("rank", "title", "year")))
peliculas[, c(1, 2, 6, 7)] <- list(NULL)
colnames(peliculas) <- c("weekend", "gross", "weeks", "title", "year")
peliculas$title <- gsub("^ +|+ $", "", peliculas$title) 
peliculas$year <- gsub("[[:punct:]]|[[:space:]]", "", peliculas$year)
peliculas$gross <- as.numeric(gsub("\\$|M", "", peliculas$gross))
peliculas$weekend <- as.numeric(gsub("\\$|M", "", peliculas$weekend))
peliculas$weeks <- as.integer(peliculas$weeks)
peliculas$year <- as.integer(peliculas$year)
peliculas <- peliculas[c(4, 5, 1, 2, 3)]
peliculas
# 2014/09/22
                          title year weekend gross weeks
1               The Maze Runner 2014    32.5  32.5     1
2   A Walk Among the Tombstones 2014    13.1  13.1     1
3     This Is Where I Leave You 2014    11.9  11.9     1
4                  No Good Deed 2014    10.2  40.1     2
5                Dolphin Tale 2 2014     9.0  27.1     2
6       Guardians of the Galaxy 2014     5.2 313.7     8
7                 Let's Be Cops 2014     2.7  77.2     6
8  Teenage Mutant Ninja Turtles 2014     2.6 185.0     7
9                      The Drop 2014     2.0   7.7     2
10                    If I Stay 2014     1.8  47.7     5

Recaudación del fin de semana

# Especificamos los márgenes del área del gráfico
par(mar = c(5, 15, 4, 2))
# Creamos el gráfico de barras horizontal
bp <- barplot(rev(peliculas$weekend), 
              names.arg = rev(peliculas$title),
              horiz = TRUE, 
              col = "lightskyblue", border= "white", 
              xlim = c(0, 35), xlab = "USD $ Millions",
              las = 1)
# Añadimos etiquetas a las barras
text(y = bp, x = 0, round(rev(peliculas$weekend), 1), pos = 4) 

Recaudación acumulada

# Ordenamos descendentemente por recaudación acumulada (gross)
peliculas <- peliculas[order(-peliculas[,4]), ] 
# 2014/09/22
                          title year weekend gross weeks
6       Guardians of the Galaxy 2014     5.2 313.7     8
8  Teenage Mutant Ninja Turtles 2014     2.6 185.0     7
7                 Let's Be Cops 2014     2.7  77.2     6
10                    If I Stay 2014     1.8  47.7     5
4                  No Good Deed 2014    10.2  40.1     2
1               The Maze Runner 2014    32.5  32.5     1
5                Dolphin Tale 2 2014     9.0  27.1     2
2   A Walk Among the Tombstones 2014    13.1  13.1     1
3     This Is Where I Leave You 2014    11.9  11.9     1
9                      The Drop 2014     2.0   7.7     2
# Márgenes del área del gráfico
par(mar = c(5, 15, 4, 2))
Gráfico de barras
bp <- barplot(rev(gross), 
              names.arg = rev(title), 
              horiz = TRUE, 
              col = "lightsalmon", border= "white", 
              xlim = c(0, 350), xlab = "USD $ Millions",
              las = 1)
# Etiquetas de las barras
text(y = bp, x = 0, round(rev(gross), 1), pos = 4) 

Entradas relacionadas

2014-09-24

Gráfico de la función de densidad de la distribución normal en R

Title En R, vamos a crear el gráfico de la función de densidad de la distribución normal usando dos funciones: plot y curve.

Función plot

Creamos un vector con las coordenadas x, en los argumentos de seq (secuencia) especificamos los límites y el número de valores intermedios o el incremento. En las coordenadas y, la función de densidad dnorm, por defecto una distribución normal estándar, N(0, 1), con una media de 0 y una varianza de 1.

x <- seq(-3, 3, 0.001) # Incremento de la secuencia: 6001 valores
# O bien
x <- seq(-3, 3, length = 1000) # 1000 valores intermedios

Usamos la función plot:

plot(x,          # Coordenadas x
     dnorm(x),   # Coordenadas y
     type = "l", # Tipo de gráfico líneas
     las = 1)    # Alineación horizontal de etiquetas

Función curve

No es necesario crear un vector con las coordenadas x. Solamente especificar el nombre de la función que evaluará: dnorm. Por defecto, curve evalua 101 valores (n = 101).

curve(dnorm(x), xlim = c(-3, 3), las = 1)

Más ejemplos

Dos ejemplos con distribuciones distintas de la distribución normal estándar. En este caso, sí es necesario suministrar los argumentos: media y desviación típica (raíz cuadrada de la varianza). Añadimos el parámetro xaxp para forzar el número de marcas del eje x entre las dos coordenadas de los extremos.

N(-2, 0.5)

x <- seq(-5, 5, 0.001)
plot(x, dnorm(x, -2, sqrt(.5)), type = "l", las = 1, xaxp =c(-5, 5, 10))
N(0, 0.2)

curve(dnorm(x, 0, sqrt(.2)), -5, 5, las = 1, xaxp = c(-5, 5, 10))
Referencias:
Nube de datos