2014-08-29

Cargar varios paquetes simultáneamente en R

Title Anteriormente tratamos la manera de instalar y cargar paquetes en R. En aquella entrada vimos como instalar múltiples paquetes.

install.packages("paquete1") # Un paquete
install.packages(c("paquete1", "paquete2", "paquete3")) # Varios paquetes

Para cargar múltiples paquetes podríamos pensar en usar la función c (combinar). Sin embargo, generará un error y no nos permitirá cargar ningún paquete.

library("paquete1") # O bien
require("paquete1")
library(c("paquete1", "paquete2", "paquete3")) # Generaría un error
require(c("paquete1", "paquete2", "paquete3")) # Generaría un error 

Solución

Para cargar múltiples paquetes usamos el siguiente código encontrado en stackoverflow

paquetes <- c("paquete1", "paquete2", "paquete3")
lapply(paquetes, require, character.only = TRUE)
En la primera línea le indicamos un vector con los paquetes que queremos instalar. Después pasamos dicho vector a la función lapply que empleará la función require para cada elemento del mismo. Incluimos el argumento character.only = TRUE pues paquetes es un vector de caracteres. En la consola, la función require devolverá un TRUE por cada paquete instalado con éxito.

Referencias

2014-08-27

Asignar método de teclado abreviado a macro en Excel

Title En Excel podemos asignar una macro a un método de teclado abreviado de dos maneras. Partimos de la siguiente macro a la que asignaremos un atajo (método de teclado abreviado).

Sub Macro1()
'Ejemplo:
  MsgBox "Funciona"
End Sub

Cuadro de diálogo Macro

1. Si no dispones de las ficha Programador visita esta página.
2. En la ficha Programador, en el grupo Código, haga clic en Macros.
3. Selecciona la macro y clic sobre Opciones.
4. Teclea la letra deseada. Para emplear mayúsculas, presiona simultáneamente Mayús y la letra.

Más rápido aún:

1. Presionar Alt + F8 y clic en Opciones.
2. Teclea la letra deseada. Para emplear mayúsculas, presiona simultáneamente Mayús y la letra.

Programáticamente con VBA

El siguiente código asigna Ctrl+Mayús+U a la macro anterior.

Sub AsignaAtajo()
 Application.OnKey "^+u", "Macro1"
End Sub
El siguiente código inhabilita la secuencia Ctrl+Mayús+U.
Sub AsignaAtajo()
 Application.OnKey "^+u", ""
End Sub
Referencias:
Método Application.OnKey (Excel) Para especificar caracteres que no están visibles al presionar la tecla, por ejemplo, TAB (tabulador), utilice los códigos que se muestran en la siguiente tabla. Cada código de la tabla representa una tecla del teclado:

2014-08-24

Asignar método de teclado abreviado a macro con VBA en Word

Title Anteriormente vimos la manera de asignar un método abreviado de teclado a una macro. En esta ocasión asignamos esa macro a un método de teclado abreviado mediante código VBA.

Macro a asignar

Sub Pegar()    
   Selection.PasteSpecial Link:=False, DataType:=wdPasteText
End Sub

Código para asignar la macro a Ctrl + Mayús +V

 Sub AsignaAtajoWord()
    With Application
         ' Ámbito de la personalización
        .CustomizationContext = NormalTemplate
         
         ' Asigna la macro Pegar al atajo: Ctrl+Mayús+V
        .KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyControl, _
        wdKeyShift, wdKeyV), _
        KeyCategory:=wdKeyCategoryCommand, _
        Command:="Pegar" 'Nombre de la macro
    End With
End Sub
Referencias:
Propiedad Application.CustomizationContext Word)
Crear método abreviado de teclado

2014-08-22

Importar datos en R: tablas HTML gráficos ggplot2

Title En la entrada anterior creamos un diagrama de dispersión y un histograma usando el paquete estándar graphics. Vamos a crear unos gráficos similares usando ggplot2, no incluidos en la entrada anterior para no hacerla innecesariamente larga.

Ejecutamos el código de los apartados importación y manipulación de la entrada anterior y comenzamos a usar ggplot2.

ggplot2

install.packages("ggplot2") # Instalamos ggplot2
library(ggplot2) # Cargamos el paquete
intervalos <- seq(1920, 2020, 10) # Intervalos
# Diagrama de dispersión
ggplot(peliculas, aes(x = year, y = rating))+
       geom_point(color = "red", size = 3)+
       scale_x_continuous( breaks = seq(0, 3000, 10))+
       theme_classic()
# Histograma personalizado 
ggplot(peliculas, aes(x = year,y = ..count..))+
     geom_histogram(binwidth = 10, colour = "white", fill = "steelblue")+
     ylab(NULL) + ylim(c(0, 60))+
     scale_x_continuous(breaks = intervalos)+
     stat_bin(binwidth = 10, aes(label=..count..), vjust=-0.5, geom = "text")
# Histograma con gradiente de color por nº de películas
ggplot(peliculas, aes(x = year))+
  geom_histogram(binwidth = 10, colour = "white", aes(fill = ..count..))+
  ylab(NULL) + ylim(c(0, 60))+
  scale_x_continuous(breaks = intervalos)

Entradas relacionadas:

2014-08-20

Importar datos en R: tablas HTML

Title Con R podemos leer tablas HTML dentro de un documento HTML. Como ejemplo vamos a la leer la siguiente tabla con las 250 películas más votadas en la imdb.

Importación

Para importar tablas HTML con R necesitamos instalar el paquete XML pensado para leer y crear documentos XML y HTML.

Usamos la función readHTMLTable cuyos argumentos fundamentales son:

url
which: el número de tabla del documento HTML
stringsAsFactors = FALSE para evitar que convierta los caracteres en factores.

library(XML)
url <- "http://www.imdb.com/chart/top" 
peliculas <- readHTMLTable(url, which = 1, stringsAsFactors = FALSE)
Una vez creado el data frame películas, podemos usar las siguientes funciones para inspeccionarlo, editarlo y ver sus propiedades.

head(peliculas) # 6 primeras filas
tail(peliculas) # 6 últimas filas
edit(peliculas) # Abrir en editor de texto
fix(peliculas) # Editar el objeto
dim(peliculas) # Nº filas y columnas
names(peliculas) # Nombre de las columnas
str(peliculas) # Propiedades 

Manipulación

En la imagen anterior vemos que tenemos un problema con los datos importados. La primera y la última columna están en blanco. La segunda contiene la posición (rank), el título (title) y el año (year). La valoración (rating) es un vector de caracteres en lugar de numérico. Varias columnas incluyen \n.

El primer problema que vamos a atacar es dividir la segunda columna en tres: rank, title y year. Para ello empleamos la función colsplit del paquete reshape2.

library(reshape2) # Para usar la función colsplit
peliculas  <-  transform(peliculas, peliculas = colsplit(peliculas[[2]], pattern = "\n", names = c('rank', 'title', 'year')))
Eliminamos las columnas sobrantes y redundantes y les asignamos nuevos nombres.

peliculas[, c(1,2,4,5,6)] <- list(NULL)
colnames(peliculas) <- c("rating", "title", "year")

Aún así seguimos teniendo algunos problemas por resolver. El rating es una vector de caracteres no un vector numérico. En title hay espacios delante y detrás de los títulos. En year los años están entre paréntesis, con espacios delante y detrás, y es un vector de caracteres. Además, las columnas están desordenadas.

peliculas$title <- gsub("^ +|+ $", "", peliculas$title) 
peliculas$year <- gsub("[[:punct:]]|[[:space:]]", "", peliculas$year) 
peliculas$rating <- as.numeric(peliculas$rating)
peliculas$year <- as.integer(peliculas$year)
peliculas <- peliculas[c(2,3,1)]  # Ordena columnas

Gráficos

Representamos los datos para poder ver en que años se concentran las películas mejor valoradas. Empleamos el paquete estándar graphics cargado por defecto. En otra entrada creamos los gráficos con ggplot2.

# Gráficos muy sencillos
plot(x = peliculas$year, y = peliculas$rating) # Gráfico de dispersión
hist(peliculas$year) # Histograma
Con el siguiente diagrama de dispersión se aprecia la concentración de películas en las últimas décadas.

Con el histograma contamos el número de películas dentro de cada década.

Refinamos y personalizamos el histograma para conocer exactamente el número de películas por década.

# Gráfico personalizado
intervalos <- seq(1920, 2020, 10)
hist(peliculas$year,
     breaks = intervalos,
     right = FALSE,
     col = "steelblue",
     border = "white",
     labels = TRUE,
     main = "nº de películas",
     xaxt = "n",         
     yaxt = "n",
     xlab = "Año",        
     ylab = NULL,
     ylim = c(0, 60))
axis(side = 1, at = intervalos)
Para ver gráficos similares generados con el paquete ggplot2 visita esta entrada.

Tabla de frecuencias

Si en lugar de explorar visualmente, creamos directamente una tabla de frecuencias.

intervalos <- seq(1920, 2020, 10)
frecuencias <- cut(peliculas$year,
                   breaks = intervalos,   
                   dig.lab = 4,   # Nº de dígitos de los intervalos
                   right = FALSE) # Intervalos [a, b). Por defecto: (a, b]
tabla.frec  <- table(frecuencias)   # Crea la tabla de frecuencias
as.data.frame(tabla.frec) 
# Tabla de frecuencias
   frecuencias Freq
1  [1920,1930)    4
2  [1930,1940)    7
3  [1940,1950)   15
4  [1950,1960)   30
5  [1960,1970)   21
6  [1970,1980)   21
7  [1980,1990)   30
8  [1990,2000)   43
9  [2000,2010)   54
10 [2010,2020)   25

Observaciones

Suponiendo un nivel de cantidad y calidad constante, esperaríamos unas 25 películas por década. Sin embargo, las películas más recientes están excesivamente representadas. Aún queda la mitad de la década de 2010-2020 y ya hay 25 películas dentro de las 250 mejores.

Posibles factores:

  • La cantidad de películas producidas y conservadas no es constante. Por ejemplo, de acuerdo a David Bordwell, aproximadamente apenas el 20% del cine mudo ha sobrevivido.
  • La calidad, apreciación, acceso y exposición a las películas no son uniformes en el tiempo.
  • IMDb no está disponible desde 1920 para que los usuarios, tras ver la película estrenada, puedan votarla. Se exige un mínimo de 25.000 votos para que una película entre en la lista.
  • IMDb, empresa subsidiaria de Amazon, se centra en los estrenos, trailers y noticias más recientes, no en la evaluación crítica de las películas de la historia del cine.
  • La edad y el perfil de los usuarios que la IMDb considera para elaborar la lista (regular voters).

Otro factor a considerar es el recency effect. Se trata de un sesgo cognitivo que explica que se pondere más, se de más importancia y se recuerde mejor los elementos más recientes.

Referencias:

2014-08-18

Importar datos en R: ficheros de texto

Title La función read.table es la manera más cómoda de importar datos en formato rectangular (hoja de datos) en R. Con ella R importa un fichero en formato rectangular y crea un data frame. Los principales argumentos son:

file - Nombre del fichero importado. Si no se incluye la ruta absoluta, R interpreta que el fichero se encuentra en el directorio de trabajo. También admite una URL completa.
header - Por defecto FALSE. Si la primera fila contiene los nombres de las variables TRUE.
sep - El delimitador, por defecto es sep = ""
quote - Cualificador de texto
dec - Separador decimal

Las funciones read.csv, read.csv2, read.delim, read.delim2 y read.fwf son versiones de la función read.table idénticas salvo por los argumentos que por defecto incluyen. Sirven como atajos o envoltorios (wrappers) con los argumentos apropiados por defecto.

read.csv: para importar ficheros separados por comas, con el punto como separador decimal.
read.csv2: para importar ficheros separados por punto y coma, con la coma como separador decimal.
read.delim: para importar ficheros delimitados por la tabulación con el punto como separador decimal.
read.delim2: para importar ficheros delimitados por la tabulación con la coma como separador decimal. read.fwf: para importar ficheros delimitados por un ancho fijo entre las columnas.

Ejemplos

ruta <- "http://www.cyclismo.org/tutorial/R/_static/simple.csv"
simple <- read.table(ruta, header= TRUE, sep = ",")
head(simple)
ruta <- "http://www.cyclismo.org/tutorial/R/_static/simple.csv"
simple2 <- read.csv(ruta)
head(simple2)
Con read.csv por defecto header = TRUE, por lo que no es necesario especificarlo como con read.table.

  trial mass velocity
1     A 10.0       12
2     A 11.0       14
3     B  5.0        8
4     B  6.0       10
5     A 10.5       13
6     B  7.0       11
read.table transforma las variables de caracteres en factores. Para evitarlo, introducimos el argumento as.is o stringsAsFactors.

# Comprueba que la variable es un factor
str(simple) # Todas las variables o trial
is.factor(x = simple$trial) 
# Evita que read.csv transforme los vectores de caracteres en factores.
simple2 <- read.csv(ruta, as.is = TRUE) 
simple <- read.csv(ruta, stringsAsFactors = FALSE)
Para seleccionar el fichero mediante un cuadro de diálogo usamos la función file.choose

fichero <- read.table(file.choose(), header= TRUE, sep = ",")
fichero <- read.csv(file.choose())

Tras la importación

A continuación algunas funciones para obtener información sobre los datos importados. Parte de la información es redundante.

 # Ver datos
head(simple) # Muestra las 6 primeras filas 
tail(simple) # Muestra las 6 primeras filas 
View(simple) # Abre visor con los datos importados
 # Atributos y estructura
names(simple) # Devuelve los nombres de las variables (columnas)
attributes(simple) # Obtenemos los atributos del objeto
dim(simple) # Número de filas por columnas (observaciones y variables)
sapply(simple, class) # Class type
sapply(simple, mode) # Mode
str(simple) # Estructura del objeto
summary(simple) # Resumen por variable
# Editar los datos
simple <- edit(simple) # Edita y reasigna
fix(simple) # Edita directamente sobre el objeto

En RStudio

1. Environment > Import Dataset > From Text File o From Web URL

2. Seleccionamos el fichero y se abre este cuadro de diálogo:

3. Modificamos las selecciones si fuera necesario y presionamos Import.

RStudio crea un data frame con el nombre del fichero importado y nos lo muestra con la función View. En RStudio el límite de filas mostradas es 1.000.

Referencias:
?read.table

2014-08-15

Listar campos y elementos calculados de una tabla dinámica

Title Si queremos que Excel cree una nueva hoja con los campos y elementos calculados de una tabla dinámica seguimos los siguientes pasos:

1. Clic en cualquier celda de la tabla dinámica.

2. En la parte superior aparecerá Herramientas de tabla dinámica y dos nuevas pestañas, pinchamos sobre la ficha Opciones.

3. Clic sobre el icono Campos, elementos y conjuntos y sobre Crear lista de fórmulas

Excel inserta una nueva hoja en la que lista los campos y elementos calculados de la tabla seleccionada.

VBA

Usamos el método PivotTable.ListFormulas (Excel)

1. Hacemos clic sobre una celda de la tabla dinámica.

2. Ejecutamos la siguiente macro que creará una hoja.

Sub CrearListaCampos()
 On Error GoTo ErrHandler:
 ActiveCell.PivotTable.ListFormulas
 Exit Sub
ErrHandler:
 MsgBox "Selecciona una celda" _
        & " de una tabla dinámica", vbCritical
End Sub
Excel inserta una nueva hoja en la que lista los campos y elementos calculados de la tabla seleccionada. En caso de no haber seleccionado una celda de una tabla dinámica aparecerá el siguiente mensaje de error:

2014-08-12

Listar todos los nombres de libro de Excel

Title Para listar los nombres definidos de un libro de Excel usamos el siguiente código. Crea una nueva hoja en la que lista todos los nombres del libro y autoajusta el ancho de las dos columnas.

Creando una nueva hoja

Sub ListarNombres1()

    Dim wks As Worksheet
    Set wks = Worksheets.Add
    wks.Range("A1").ListNames
    wks.Columns("A:B").Columns.AutoFit

End Sub
Más simplificadamente aún:

Sub ListarNombres2()

    Sheets.Add
    Range("A1").ListNames
    Columns("A:B").AutoFit

End Sub

Cuadro de diálogo

Otra opción que he escrito, consiste en elegir mediante un cuadro de diálogo el rango donde queremos que liste los nombres.

Sub ListarNombres3()

    Dim myRange As Range
    Set myRange = Application.InputBox(Prompt:="Selecciona celda vacía", _
    Title:="Listado de nombres", Type:=8)
    myRange.ListNames
    
End Sub
El inconveniente de la macro anterior es que al copiar el listado de nombres, si no sabemos el número de nombres del libro, puede sobreescribir celdas. Para evitarlo he creado el siguiente código. Crea una hoja temporal con el listado de nombres y, a partir de la celda seleccionada, calcula si el rango necesario para copiar los nombres está vacío o no. Si no lo está, no copiará el listado de nombres.

Sub ListarNombres4() 

    Dim sInicial As String
    sInicial = ActiveSheet.Name
    Dim sName As String
    Worksheets.Add.Name = "temp"
    Sheets("temp").Range("A1").ListNames
    Dim i As Integer
    i = [COUNTA(temp!A:A)]
    Sheets(sInicial).Select
    
    On Error GoTo Final
    Dim myRange As Range
    Set myRange = Application.InputBox(Prompt:="Elige celda con" & _
        " región vacía alrededor de 2 columnas por" & i & " filas", _
        Title:="Listado de nombres", Type:=8)
            If RangeIsBlank(myRange.Resize(i, 2)) = False Then
              MsgBox "Rango no vacío. No se puede copiar aquí.", vbCritical
              GoTo Final
              Else
            End If
    myRange.ListNames
    myRange.Resize(i, 2).Columns.AutoFit
    
Final:
        Application.DisplayAlerts = False
        Worksheets("temp").Delete
        Application.DisplayAlerts = True

End Sub
Para emplear la macro anterior es preciso incluir en un módulo del libro la siguiente función de Dick Kusleika.

Function RangeIsBlank(rRng As Range) As Boolean
    
    If IsNull(rRng.FormulaArray) Then
        RangeIsBlank = False
    Else
        RangeIsBlank = Len(rRng.FormulaArray) = 0
    End If
    
End Function

2014-08-09

Visualizar la historieta XKCD en R

Title

XKCD es una historieta cómica web creada por Randall Munroe dedicada a temas relacionados con la ciencia. Su lema completo es: a webcomic of romance, sarcasm, math, and language. Su principal aliciente y frecuentemente fuente de frustraciones consiste en descifrar los múltiples juegos de alusiones que encierra. Podemos recurrir a explain xkcd donde seguidores del cómic glosan cada una de las historietas.

Paquete XKXD

El paquete RXKCD en R nos permite ver nuestras viñetas de XKCD favoritas directamente en R y buscar palabras claves incluidas en el título o en las notas de la historieta. Básicamente consta de dos funciones:

1. getXKCD

Recupera y muestra la historieta que le indiquemos o bien aleatoriamente.

Los argumentos por defecto son:

getXKCD(which = "current", display = TRUE, html = FALSE,
    saveImg = FALSE)
which: "current" (la última), "random" (aleatoria) o el número de la historieta
display: TRUE para mostrarla en pantalla, o no FALSE
html: TRUE para abrirla en nuestro navegador, o no FALSE
saveImg: guarda la imagen en el directorio actual

Ejemplos:

# Última Historieta publicada
getXKCD()
# Historieta aleatoria
getXKCD(which = "random")
# Historieta 243 mostrada en el navegador
getXKCD(243, html = TRUE)

2. searchXKCD

Localiza historietas con el texto especificado en los títulos y notas de las historietas.

Ejemplo para localizar la historieta relacionada con la anterior: 243

# Busca la cadena keyboards
searchXKCD("keyboards")
# Muestra dos columnas con el número y título de la historieta
  num                    title
1 237 Keyboards are Disgusting
2 243         Appropriate Term
Nube de datos