Técnicas Informáticas para la Estadística

Índice

1. Ubuntu

1.1. aula B03

  • 20 ordenadores portátiles (numerados desde MANADINE-01 hasta MANADINE-20)
  • dos tipos
    • la mayoría tiene arranque dual mediante GRUB:
      • 10 segundos para elegir
        • Ubuntu
        • Windows Boot Manager
      • en ambos, úsese la cuenta manadine (en algunos se entra automáticamente en ella)
    • MANADINE-01, MANADINE-04 y MANADINE-12 tienen Ubuntu a través de GRUB y Windows en VirtualBox
      1. dejar que arranque GRUB (tras tres segundo inicia Ubuntu)
      2. el gestor de cuentas de usuario (GDM) permite elegir entre tres:
        • Profesor de MANADINE (usuario administrador)
        • Estudiante de MANADINE (usuario sin privilegios)
        • Windows
      3. si se escoge Windows: tras apagar Windows y volver a GDM, recuérdese apagar el Ubuntu

1.2. instalación

1.3. informática libre

Definición: http://www.gnu.org/philosophy/free-sw.es.html

Libertad para

  • usar
  • copiar
  • modificar (implica acceso al código fuente del programa)
  • redistribuir

Según la importancia del desarrollo teórico o filosófico, los principales proyectos de informática libre son:

Ubuntu es un producto derivado en su mayor parte de Debian, que define su misión insistiendo en lo gratis más que en lo libre.

1.4. plataforma / arquitectura

https://www.debian.org/ports/index.es.html

  • las más extendidas:
    • PC 32 bit: i386i686 x86
    • PC 64 bit: amd64 x86_64
  • otras: arm mips sparc
usuario@ordenata:~$ uname -a
Linux ordenata 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

donde

  • Linux = nombre del núcleo
  • ordenata = nombre del ordenador en la red
  • 3.13.0-92-generic = nombre de la liberación del núcleo
  • #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 = nombre de la versión del núcleo
  • x86_64 = nombre de la máquina
  • x86_64 = nombre del tipo de procesador
  • x86_64 = nombre de la plataforma
  • GNU/Linux = nombre del sistema operativo

1.6. capas

1.6.2. gnu

1.6.3. apt (debian)

1.6.4. x

1.6.5. gnome (kde, xfce…)

1.7. terminales virtuales y sistema gráfico

En Ubuntu 22.4, habitualmente:

  • Ctrl-Alt-F1: GDM (recepción de usuarios)
  • Ctrl-Alt-F2: sesión gráfica del usuario que ha entrado en GDM
  • Ctrl-Alt-F3 (ó F4, F5, F6): terminal de texto
  • terminal en X: escribir «terminal» en el buscador o pulsar Ctrl-Alt-T

Información sobre la versión de Ubuntu:

cat /etc/lsb-release

1.8. jerarquía de directorios

1.8.1. /

La raíz del árbol de directorios. En Windows sería similar a «C:». Sin embargo, en Windows los dispositivos nuevos aparecen fuera (por ejemplo, una memoria USB puede aparecer como dispositivo «H:») mientras que en Ubuntu todos los dispositivos se montan en el mismo árbol de directorios (por ejemplo, en /media/nombreusuario/MemoriaUSB).

1.8.2. /home

En principio, cada directorio en /home se corresponde con una cuenta de usario. Por ejemplo, en la sala B08 de la Facultad de Ciencias de la Universidad Oviedo cada ordenador tiene /home/administrador y /home/alumno. Para los usuarios que acceder con su cuenta centralizada universitaria la carpeta personal se crea en /home/likewise-open/IDENT/.

1.8.3. /tmp

Directorio de ficheros temporales. Todo lo que no se quiera conservar, se puede crear o mover ahí.

1.8.4. /var

Directorio de contenidos variables del sistema. En concreto, en /var/log/ se almacenan los ficheros de registro de los diferentes servicios del sistema operativo. Por ejemplo, en /var/log/messages o /var/log/syslog.

1.8.5. /media

Aquí aparecen los ficheros de los disposivos externos, como un DVD o una memoria USB.

1.9. Introducción a la «línea de comandos»

1.9.1. Acceso remoto

AVISO: Desde octubre de 2022, si se quiere acceder a un servidor de la universidad desde fuera de su red es necesario usar autenticación de doble factor. Una posibilidad es, antes de usar SSH o PuTTY, conectar con la red privada de la uni mediante algún cliente como Forticlient VPN siguiendo por ejemplo estas instrucciones. En 2023, es posible que Forticlient ya no funcione y que haya que usar GlobalProtect (consultar en la intranet de uniovi el software corporativo de acceso remoto o gpclient con openconnect).

Para acceder con terminal a otra máquina:

ssh alumno@zadeh.ciencias.uniovi.es

Para acceder desde Windows o ReactOS, puedes usar la "línea de comandos" que se obtiene

  • pulsando la tecla windows junto con la R (erre) y luego
  • tecleando cmd y pulsando Intro

o bien mediante el programa PuTTY indicando el nombre de la máquina (p.ej. zadeh.ciencias.uniovi.es) o su dirección IP (p.ej. 156.35.96.173) y la puerta o puerto de acceso (22, por omisión y en general).

Para copiar una carpeta local a la máquina remota:

scp -rp carpetaLocal alumno@zadeh.ciencias.uniovi.es:~

o bien:

scp -rp carpetaLocal alumno@zadeh.ciencias.uniovi.es:~/carpetaRemota

Para copiar una carpeta remota a la máquina local:

scp -rp alumno@zadeh.ciencias.uniovi.es:~/carpetaRemota .

Para copiar de manera gráfica, puedes usar

1.9.2. Motivación

Crearemos una imagen pequeña a partir de una grande, primero desde la interfaz gráfica de GIMP y luego usando el comando «convert».

  1. Con GIMP.
    1. Consigue una imagen. Por ejemplo, descarga una (a la carpeta Descargas) con Firefox usando este enlace: imagen
    2. Abre el programa GIMP (o Krita o MyPaint…).
    3. En el menú Imagen de GIMP, elige la opción Escalar imagen. Adapta la imagen para que tenga 300 pixeles de anchura. Expórtala con un nombre distinto (por ejemplo, diagramas-gimp.png) y sal de GIMP.
    4. Comprueba las diferencias en tamaño de fichero respecto a la imagen original.
  2. Con ImageMagick.

    Abre un terminal y escribe

    ls
    cd Descargas
    convert -resize 300 diagramas.png diagramas-convert.png
    

    Compara el nuevo fichero creado con los que ya existían.

    Puedes salir del terminal pinchando en el aspa del marco de la ventana, o escribiendo exit o pulsando C-d (es decir, Crtl+D, simultáneamente las teclas Ctrl y D).

Otro ejemplo con R e Imagemagick:

setwd("/tmp") # trabajaremos en el directorio temporal
png()         # crearemos >600 ficheros de imágenes
for (angulo in seq(0,2*pi,0.01)) # en radianes
    plot (cos(angulo), sin(angulo), # recorremos circunferencia
          xlim=c(-1,1), ylim=c(-1,1)) # para que coincidan ejes
dev.off()     # cerramos el desvío de gráficos a ficheros
## pueden pegarse las imágenes con:
## $ cd tmp
## $ convert -delay 1 -loop 0 Rplot*.png anime.gif

1.9.3. Preparación de ejemplos

  1. Crea una carpeta con el nombre textos dentro de Descargas.
  2. Descarga1 dentro de textos los ficheros disponibles en http://bellman.ciencias.uniovi.es/~carleos/master/manadine/curso1/TIplE/ejercicios/datos/textos
  3. Abre un terminal.

Todo lo que se escribe a continuación de una almohadilla2 «#» se considera un comentario y no se ejecuta:

# esto es un comentario

1.9.4. Ayuda

man ls         # página de manual sobre ls; q para salir;
apropos rename # comandos cuya descripción contiene rename
  • Algunos comandos que usaremos (como cd) no contienen ayuda propia. Están documentados en el manual del intérprete de comandos (man bash).
  • Todo paquete de Ubuntu tiene documentación guardada en el directorio /usr/share/doc/
  • Buscando por internet, hay foros como Stackoverflow o Askubuntu cuyos usuarios resuelven problemas concretos.

Otros manuales están disponibles con la orden info. En concreto, muchas de las órdenes que veremos están disponibles en coreutils:

info coreutils        # q para salir;

1.9.5. Opciones

Los comandos tienen un comportamiento por omisión, que puede ser modificado mediante opciones (que suelen comenzar con un guion «-»):

uname      # por omisión da el nombre del núcleo del sistema operativo
uname -a   # «a» significa «all»; da más información;

1.9.6. Rutas

La carpeta personal se representa abreviadamente por una virgulilla: ~

La carpeta personal de otro usuario se representa abreviadamente por una virgulilla seguida por el nombre de usuario; por ejemplo: ~carleos

Los directorios se separante mediante barras: /

La ruta desde la raíz al directorio actual puede conocerse ejecutando

pwd

Su nombre significa «print working directory».

(En R, la instrucción equivalente sería getwd()).

1.9.6.1. Rutas absolutas

Tienen como referencia un punto fijo de la jerarquía de directorios. Dicho punto suele ser:

  • La raíz de la jerarquía de directorios

    ls /usr/share/doc
    

    En estos casos la ruta comienza por una barra /.

    (En R se usaría dir("/usr/share/doc")).

  • El directorio personal:

    ls ~/Descargas/textos
    

    En estos casos la ruta comienza por una virgulilla ~.

1.9.6.2. Rutas relativas

No comienzan por barra ni virgulilla:

Los dos puntos .. son un nombre especial de directorio, y significan subir un nivel en la jerarquía.

Un solo punto «.» representa el directorio actual. Por ejemplo, si estamos en ~/Documentos y queremos copiar ahí el fichero ~/Descargas/textos/texto1:

cd ~/Documentos                       # entramos en la carpeta ~/Documentos
cp ../Descargas/textos/texto1 .       # copiamos el fichero texto1 a la carpeta actual, es decir, ~/Documentos

(En R, se usaría:

setwd("~/Documentos")
file.copy("../Descargas/textos/texto1", ".")

).

1.9.7. Comandos básicos

1.9.7.1. cd (cambiar directorio)

Cambiar directorio actual:

cd ~/Descargas/textos     # nos movemos a la carpeta «textos»;
cd ..                     # subir un nivel en la jerarquía de directorios, es decir, a «Descargas»;
cd                        # ir al directorio personal; equivale a «cd ~»;
cd -                      # volver al directorio anterior; aquí, de nuevo a «Descargas»;

En R: setwd()

1.9.7.2. ls (listar contenido)
ls             # sólo nombres de ficheros;
ls -l          # más información;
ls -lrt        # ordenados; al final, los más nuevos;
ls -lrth       # tamaños más legibles;
ls -a          # muestra también los ocultos;

En R: dir()

1.9.7.3. md5sum, sha256 (comprobar integridad)

Para comprobar que un fichero descargado se corresponde con el alojado en el servidor, a menudo se publica un "resumen" del fichero calculado con un algoritmo de "hash". Hasta hace poco, el más usado era MD5, aunque ya se considera inseguro y se están popularizando los algoritmos SHA-2.

md5sum *       # da el MD5 de los ficheros del directorio actual

De forma similar pueden usarse ‘sha224sum’, ‘sha256sum’, ‘sha384sum’ y ‘sha512sum’.

1.9.7.4. cp (copiar)

Copiar ficheros:

cd /tmp
cp ~/Descargas/textos/texto1 . # al directorio actual, /tmp

Copiar directorios:

cd /tmp
cp -a ~/Descargas/textos .     # al directorio actual, /tmp

En R: file.copy()

1.9.7.5. mv (mover o renombrar)

Renombrar o mover ficheros.

cd /tmp
cp texto1 texto1bis
mv texto1 texto-primero                # mv nombreviejo nombrenuevo
mv texto-primero textos/texto-PRIMERO  # mv nombreviejo nuevo/directorio/contenedor/nombrenuevo
mv texto1bis textos                    # mv fichero nuevo/directorio/contenedor

En este último caso, en que no se cambia el nombre, pueden moverse varios ficheros:

cd /tmp/textos
mkdir otra-carpeta
mv texto1 texto2 texto3 otra-carpeta

Por si acaso machacamos otro fichero, podemos exigir confirmación interactiva:

mv -i nombreviejo nombrenuevo

Por ejemplo,

cd /tmp/textos/otra-carpeta
mv -i texto1 texto2                   # ¡aviso!  confirmar sustitución de texto2 por texto1

En R: file.rename()

1.9.7.6. rm (borrar)

Eliminar ficheros…

rm /tmp/textos/otra-carpeta/texto2

…y directorios:

rm -rf /tmp/textos

Esto último el peligroso, porque no lo envía a ninguna «papelera»3. Por precaución sería recomendable no eliminar las cosas directamente, sino moverlas a una carpeta al efecto (p.ej. Descargas).

En R: file.remove()

1.9.7.7. mkdir (crear directorio)

Crear directorios:

mkdir ~/manadine
rmdir ~/manadine   # borrarlo, si está vacío
rm -rf ~/manadine  # borrarlo, ¡aunque esté ocupado!

En R: dir.create()

1.9.7.8. Ver contenido de ficheros

Para volcar todo el contenido al terminal:

cat /usr/share/common-licenses/GPL

(En R se puede obtener un vector de renglones mediante

  • readLines("/usr/share/common-licenses/GPL")
  • o bien

    system("cat /usr/share/common-licenses/GPL", intern=TRUE)
    

).

Se usa a menudo para procesar el contenido con otro comando:

wc /usr/share/common-licenses/GPL # contar renglones, palabras y caracteres
cat /usr/share/common-licenses/GPL | wc # equivale al anterior

Para ver el contenido "paginado" se usa more o less:

less /usr/share/common-licenses/GPL

Para avanzar, pulsar espacio, o flecha abajo, o avanzar página.

Para retroceder, pulsar "b", o flecha arriba, o retroceder página.

Para salir, pulsar "q".

Para ir al principio, pulsar "p".

Para buscar, pulsar "/" y teclear lo buscado.

Luego "n" para avanzar a siguientes ocurrencias de la búsqueda, "N" para las anteriones.

Para volcar sólo una parte del fichero:

head fichero        # 10 primeros renglones
head -n 15 fichero  # 15 primeros
tail -n 20 fichero  # 20 últimos
cut -c 1-40 fichero # 40 primeros caracteres de cada renglón
1.9.7.9. Editar ficheros de texto

Para hacer modificaciones en ficheros de texto en un terminal, puede usarse nano:

nano ruta/al/fichero.txt

Por omisión, muestra en la parte inferior las combinaciones de teclas para usarlo. Por ejemplo ^X (circunflejo equis) significa pulsar las teclas Ctrl y X (se usa para salir).

Hay editores mucho más completos, como vi y emacs, pero son más difíciles de usar.

Si puede usarse un entorno gráfico, puede ser más cómodo usar un editor como gedit o notepad++ o rstudio.

1.9.8. Comodines

ls /var/log/alternatives*gz       # * sustituye múltiples caracteres
ls /var/log/alternatives.log.?.gz # ? sustituye un único carácter
cd /var/log
ls alternatives.log.[467].gz      # 4 ó 6 ó 7
ls alternatives.log.[4-7].gz      # rango de 4 a 7
ls alternatives.log.[^4-7].gz     # fuera del rango de 4 a 7
ls alternatives.log.{1,2}.gz      # .log.1 y .log.2.gz

1.9.9. Tubos (pipes)

La salida de un comando puede guardarse en un fichero mediante un ángulo «mayor que»: >

ls /usr/share/doc >  /tmp/lista1.txt                      # redirige stdout
cat ~/Descargas/textos/texto* > ~/Descargas/textos-juntos # pega varios ficheros

La salida de un proceso puede aprovecharse «al vuelo» mediante un tubo «|»:

ls -lR / | head -n 20 # para ver los 20 primeros renglones
ls | wc -l            # cuántos ficheros no visibles hay en el directorio actual
head -n 1 /etc/passwd | tr ' ' '_' | tr ':' ' ' | wc -w # contar campos
tail /etc/passwd | cut -d ':' -f 1,5,6 # tres campos de los últimos 10 renglones

El programa «tee» (T) permite redirigir la salida a un fichero al tiempo que se aprovecha en un tubo:

ls -lR / | tee /tmp/todos-los-ficheros.txt | less

1.9.10. Filtros

Si queremos quedarnos sólo con algunos de los renglones de la salida de un comando, podemos usar el comando grep. Por ejemplo, para quedarnos con los nombres de los ficheros en /var/log cuyos nombres contienen la secuencia natives:

ls /var/log | grep natives

Ahora, los que acaben en gz:

ls /var/log | grep gz$

Ahora, los que empiecen por kern:

ls /var/log | grep ^kern

Igualmente pueden filtrarse los renglones de un fichero. Las dos órdenes siguientes son equivalentes:

grep GNU /usr/share/common-licenses/GPL
cat /usr/share/common-licenses/GPL | grep GNU

1.9.11. Comprimir

Para comprimir un fichero se usa gzip:

gzip fichero.txt

Desaparece fichero.txt y aparece el fichero fichero.txt.gz.

Para descomprimir un fichero se usa gunzip:

gunzip fichero.txt.gz

El fichero se convierte en fichero.txt.

También hay otros compresores y empacadores famosos (bzip2, 7zip, xz, unzip, unrar, tar…)

1.9.12. Búsquedas

El comando locate busca los ficheros en un banco de datos que genera periódicamente el sistema. Por la tanto, puede que no encuentre ficheros de reciente creación. Para estos últimos hay que usar find.

locate alternatives                   # búsqueda rápida (aunque no actual del todo)
find /var/log -name '*alternatives*'  # buscar ficheros actualmente en un directorio
find /var/log -iname '*ALTERNATIVES*' # búsqueda sin diferenciar úsculas
find  ~ -mtime -3                     # buscar los modificados hace menos de tres días
find  ~ -mtime +3                     # buscar los modificados hace más de tres días
find  ~ -mtime  3                     # buscar los modificados hace tres días (entre 72h y 96h)

Para evitar muchos mensajes de que no hay permisos:

find / -name '*alternatives*' 2>/dev/null

1.9.13. Bucles

Vamos a descargar ahora una serie de imágenes para reducirlas después todas ellas a 300 pixeles:

cd ~/Imágenes
wget -rl1 http://156.35.96.172/incubadora/edicion4/fotos/badajoz-asturianos/exposicion-equipo-Oviedo/
ls -R
cd 156.35.96.172/incubadora/edicion4/fotos/badajoz-asturianos/exposicion-equipo-Oviedo/
for i in *jpg; do convert -resize 300 $i $i-300.jpg; done

En el bucle for anterior, la cadena -300.jpg se añade al nombre del fichero original. No parece muy correcto que quede un nombre como imagen.jpg-300.jpg; lo normal es que tengamos un nombre como imagen-300.jpg. Para ello, podemos usar la orden basename, que permite eliminar la extensión del nombre de un fichero:

basename imagen.jpg .jpg    # devuelve la cadena «imagen»

Necesitamos saber cómo empotrar el resultado devuelto por una orden en otra. Para eso existe la construcción $(...). Veamos un ejemplo:

echo Hola, Mundo                  # «echo» escribe sus argumentos
expr 5 + 15                       # devuelve «20»
echo 5 + 15 = $(expr 5 + 15)      # devuelve «5 + 15 = 20»

Así, el bucle quedaría:

for i in *jpg; do convert -resize 300 $i $(basename $i .jpg)-300.jpg; done

Cuando los nombres de ficheros contienen espacios, se pueden usar comandos (find -print0, xargs -0) que separen las distintas caderas mediante un carácter especial (ASCII cero, NUL), pero nos va a ser mucho más cómodo realizar la tarea en R. Por ejemplo:

### consigue varias capturas de pantalla pulsando ImprPant
### se almacenan en ~/Imágenes
### crea las carpetas vacías ~/Imágenes/PNG y ~/Imágenes/JPG
### mete las capturas en ~/Imágenes/PNG
### convierte las capturas a ficheros JPEG dentro de ~/Imágenes/JNG

setwd ("/home/alumno/Imágenes")
f <- system ("ls PNG", intern=TRUE) # nombres de las imágenes
f <- gsub (".png", "", f, fixed=TRUE)
## instrucción de Bash:
## convert 'PNG/nombreimagen.png' 'JPG/nombreimagen.jpg'
for (nombreimagen in f)
    system (paste0 ("convert 'PNG/",
                    nombreimagen,
                    ".png' 'JPG/",
                    nombreimagen,
                    ".jpg'"))

El comando system requiere la construcción de una cadena (aquí mediante paste0) que se ejecutará en Bash. Puede ser más cómodo usar el comando alternativo system2 que permite enviar los argumentos separadamente, permitiendo proteger los nombres de ficheros aplicando shQuote. Por tanto, la orden siguiente

system ("touch '/tmp/fichero con nombre raro' /tmp/'y otro'")

equivale a

system2 ("touch", 
         sapply (c("/tmp/fichero con nombre raro", "/tmp/y otro"),
                 shQuote))

1.9.14. PDF

Vamos a explorar el contenido de un fichero PDF contenido en un servidor remoto. Primero revisaremos su contenido textual dentro del terminal puro:

ssh carleos@carleos2.epv.uniovi.es    # entramos en el servidor;
cp /home/manadine/dat/venkatraman.pdf ~ # copiamos el fichero a la carpeta personal;
cd                                    # cambiamos al directorio personal;
ls                                    # comprobamos que existe un fichero «venkatraman.pdf»;
pdftotext venkatraman.pdf             # genera «venkatraman.txt»;
less venkatraman.pdf                  # «q» para salir; «-S» si tu terminal no es suficientemente ancho;
pdftotext -layout venktraman.pdf      # genera un fichero de texto en dos columnas;
less -S venkatraman.pdf               # la opción «-S» equivale a pulsar «-S» una vez dentro;
exit                                  # terminamos la sesión remota

Ahora vamos a entrar en el servidor remoto, activando también un canal gráfico para poder ver el PDF en todo su esplendor:

ssh -Y carleos@carleos2.epv.uniovi.es    # la opción «-Y» habilita el canal gráfico
evince /tmp/ROK/venkatraman.pdf          # se abre una ventana para ver el PDF a distancia
exit                                     # salimos después de cerrar la ventana de «evince»

Por supuesto, en vez de visualizar el fichero en remoto podríamos copiarlo al ordenador local mediante una orden como

scp carleos@carleos2.epv.uniovi.es:/home/manadine/dat/venkatraman.pdf .

Para acceder remotamente desde un ordenador con Windows o ReactOS, puedes usar PuTTY. Si necesitas usar ventanas gráficas, puedes instalar Xming y activar "X11 Forwarding" en PuTTY. Otra posibilidad sería instalar en la máquina remota un servidor de escritorio remoto (VNC, Xrpd, X2go…).

Para copiar ficheros remotamente desde un ordenador con Windows o ReactOS, puedes usar WinSCP o Filezilla.

1.9.15. combinaciones útiles de teclas

1.9.15.1. en el terminal
  • C- significa Ctrl
  • M- significa Alt o pulsar antes ESC
teclas propósito
TAB completa comandos, archivos…
C-p renglón previo
C-n renglón siguiente (next)
C-b carácter a la izquierda (back)
C-f carácter a la derecha (forward)
C-a principio de renglón
C-e final de renglón
C-l limpia terminal
C-d borra carácter bajo cursor
C-k borra resto del renglón
C-y pega el texto cortado con C-k
C-u borra hasta el inicio del renglón
C-w borra la última palabra
C-r texto busca en la historia comandos con "texto"
C-s texto ídem, pero hacia abajo
M-b palabra a la izquierrda
M-f palabra a la derecha
1.9.15.2. en «man», «less»…
q
salir
SPC
página abajo
b
página arriba
p
al principio
G
al final
/
buscar hacia abajo
?
buscar hacia arriba
n
buscar siguiente
N
buscar anterior
1.9.15.3. en «info»
q
salir
SPC
página abajo
DEL
página arriba (delete = suprimir)
RET
entrar en apartado (return = intro)
b
al principio
e
al final
/
buscar hacia abajo
s
buscar hacia abajo
n
apartado siguiente
p
apartado anterior
u
arriba (up)
t
comienzo del documento (top)
l
volver (last)
d
directorio de todos los info

Más información escribiendo info info

2. R

2.1. Instalación

2.1.1. ReactOS y Windows

  • Descargar el último R desde https://cran.r-project.org/bin/windows/base
  • Ejecutar el fichero .exe descargado (actualmente, versión 3.4.1).
  • Pulsar Siguiente hasta el diálogo Opciones de configuración. Ahí elegir y pulsar Siguiente.
  • Elegir en Modo de display la opción SDI - ventanas separadas.
  • Mantener las opciones por omisión en el resto de diálogos, hasta Instalando.
  • Ejecutar R pinchando el icono R x64 3.4.1.
  • Ejecutar en la consola de R la orden

    install.packages(c("actuar","Rcmdr","boot","bootstrap","evd","extRemes","pwr","mcmc","survey","sampling","SDaA","pps",
                       "pwr","TeachingSampling","TeachingDemos","RcmdrPlugin.TeachingDemos","optrees","RWeka","genalg","GA","ChainLadder"))
    
  • Ojo, en algunos ordenadores con Windows 10 hemos tenido que desinstalar R, eliminar la carpeta C:/Usuarios/nombreordenador/Documentos/R, reinstalar R desde cero, ejecutarlo como administrador y ejecutar:

    install.packages(c("actuar","Rcmdr","boot","bootstrap","evd","extRemes","pwr","mcmc","survey","sampling","SDaA","pps",
                       "pwr","TeachingSampling","TeachingDemos","RcmdrPlugin.TeachingDemos","optrees","RWeka","genalg","GA","ChainLadder",
                       "Formula","sandwich","ggplot2","acepack","base64enc","latticeExtra","gridExtra","checkmate","data.table","e1071","readxl","haven","nortest","sem","rmarkdown","multcomp","lmtest","leaps","aplpack"),lib=.Library)
    
  • Ejecutar en la consola de R la orden

    library(Rcmdr)
    
  • Cuando pregunte si instalar paquetes adicionales, pulsar .
  • Es posible que pregunte en algún momento si instalar paquetes en un directorio alternativo. Aceptar el que da por omisión.

2.1.2. Debian y Ubuntu

Ojo a la diferencia entre paquetes APT (de Debian/Ubuntu, programas empaquetados para ser fácilmente instalables en Debian/Ubuntu) y paquetes de R (bibliotecas o extensiones de R). Hay paquetes de R (por ejemplo, Rcmdr) que tienen su propio paquete de Ubuntu (siguiendo el ejemplo, r-cran-rcmdr), pero otros muchos no.

2.1.2.1. Paquetes incluidos de fábrica

Para el trabajo básico en R, puede ser suficiente utilizar los paquetes disponibles desde el « centro de software ». Para tener una buena colección de paquetes de R, puedes instalar el paquete de Ubuntu llamado r-cran-rcmdr. Ojo porque, durante la primera ejecución de Rcmdr, te pide la instalación de paquetes adicionales.

2.1.2.2. Paquetes a la última

Si necesitas un paquete de R más específico, es normal que no sea compatible con la versión de R instalada de fábrica en Debian/Ubuntu (sobre todo, si estás usando Debian Stable o Ubuntu LST, long time support).

En ese caso, hay que añadir un repositorio al APT (el sistema de paquetería que está debajo del centro de software). Resumiendo, las órdenes en Bash serían algo así:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
sudo add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu bionic-cran35/"
sudo apt update
sudo apt full-upgrade
sudo apt autoremove
sudo apt install r-base-dev libcurl4-gnutls-dev xorg-dev libglu1-mesa-dev 
## la última orden es para compilar lo siguiente desde R: 
## R> install.packages (c ("magrittr", "haven", "stringi", "Rcmdr"))
## si se produce algún fallo, probar paquete a paquete:
## R> install.packages ("magrittr")
## R> install.packages ("haven")
## R> install.packages ("stringi")
## R> install.packages ("Rcmdr")

Para hacerlo todo de una tirada:

sudo sh -c 'apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9 &&
            add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu bionic-cran35/" &&
            apt -y full-upgrade &&
            apt -y autoremove &&
            apt -y install r-base-dev libcurl4-gnutls-dev xorg-dev libglu1-mesa-dev &&
            echo "install.packages (c (\"magrittr\", \"haven\", \"stringi\", \"Rcmdr\", 
                                       \"sem\", \"rmarkdown\", \"rgl\", \"multcomp\", \"lmtest\", \"leaps\", \"aplpack\"), 
                                    repos=\"https://cloud.r-project.org\")" | R --vanilla'

Para más detalles, las instrucciones están en

(a lo que se puede llegar desde http://www.r-project.org pinchando en Download CRAN, luego eligiendo alguno de los servidores, luego pinchando en Download R for Linux y, finalmente, en la carpeta debian o ubuntu).

Nota: En octubre de 2018 dejó de funcionar en UniOvi el uso de

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9

dando el error siguiente:

gpg: recepción del servidor de claves fallida: Expiró el tiempo de conexión

La solución consiste en complementar la direción del servidor así:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9

(Referencia: https://unix.stackexchange.com/questions/75892)

2.2. Interfaces

2.2.1. Rkward

Instalable desde el paquete de Ubuntu rkward

Tiene un buen editor de datos en forma de cuadrícula o rejilla de hoja de cálculo.

En los menús sólo implementa recodificación de variables cualitativas. Las trasformaciones más complejas deben hacerse desde la consola.

2.2.2. Terminal

$ cd ~/directorio/de/trabajo
$ R
> q()                                # para salir
Save workspace image? [y/n/c]: n

Si se pulsa y para salir, entonces aparecen los ficheros .Rhistory y .RData. El primero contiene los comandos ejecutados en la sesión y el segundo alberga los objetos creados. Ejemplo:

$ R
> variable = "texto de ejemplo"
> q()
Save workspace image? [y/n/c]: y
$ R
> variable                           # comprobamos que el valor se había guardado

Si pulsamos la flecha hacia arriba (ó Ctrl-P) entonces recuperamos los comandos de la sesión anterior.

Esto es útil si arrancamos R en directorios distintos para sesiones de trabajo que tengan que ver con cosas distintas.

Para editar un programa de R dentro de la sesión, puede usarse:

$ R
> system ("gedit miprograma.R&")   # el símbolo & implica ejecución en segundo plano (asíncrona)

2.2.3. Rstudio

  1. Descargar el fichero http://rstudio.com -> Desktop -> Download -> ZIP/Tarballs -> Debian/Ubuntu 64-bit

    Se puede comprobar la integridad del fichero usando el comando md5sum.

  2. Abrir con: Gestor de archivadores
  3. Extraer en (por ejemplo) Escritorio
  4. Entrar en la carpeta =~/Escritorio/rstudio-0.99.903/bin
  5. Botón derecho sobre rstudio, elegir «Crear un enlace»
  6. Mover el nuevo Enlace hacia rstudio al Escritorio
  7. Botón derecho sobre Enlace hacia rstudio, elegir «Propiedades», pinchar en el icono y elegir ~/Escritorio/rstudio-0.99.903/rstudio.png

2.2.4. Rcmdr

Instalable como paquete de Ubuntu llamado r-cran-rcmdr o como paquete de R llamado Rcmdr.

Una vez instalado, se puede buscar directamente en el buscador de aplicaciones de Ubuntu.

Si se está ejecutando R en terminal o en Rkward o en Rstudio, se puede arrancar Rcmdr mediante:

library(Rcmdr)

Si ya se ha ejecutado esa orden y, habiendo salido de Rcmdr, se quiere volver a entrar sin salir de R, ejecútese

Commander()

Si has usado Rcmdr desde terminal, al salir de Rcmdr puede haberse corrompido el terminal. Escribiendo reset vuelve a la normalidad.

2.2.5. ESS (Emacs Speaks Statistics)

Probablemente el mejor entorno integrado para programar en R, sobre todo si prefieres moverte con el teclado en vez de con el ratón.

Emacs también es un buen entorno para programar en Octave, Maxima, \(\LaTeX\), etc.

En Ubuntu, ESS se encuentra disponible en el paquete ess.

2.3. Lenguaje

2.3.1. ayuda

Para encontrar ayuda sobre un comando de R, por ejemplo rep, puedes usar

?rep

Para algunos comandos con nombres especiales, hay que usar comillas; por ejemplo,

?"["
?"if"
help("if")

Si sólo conocemos parte del nombre del comando (p.ej. norm), usamos

apropos("norm")

Si queremos encontrar información relacionada con un concepto, podemos usar:

??variance
help.search("variance")

2.3.2. comentarios

  • si se escribe el carácter almohadilla «#» todo lo que queda a su derecha en el mismo renglón no se evalúa
  • se usa para introducir comentarios en código fuente de R

    help("if") # sirve para buscar la ayuda asociada a la orden "if"
    
  • otro uso frecuente es para desactivar parte de un programa

    # desactivo temporalmente lo relativo a la variable "z"
    x <- 10
    y <- 15
    # z <- 34
    x + y # + z
    

2.3.3. variables

  • todo objeto del lenguaje R puede almacenarse en una variable

    radio <- 10          # asignamos el valor '10' a la variable 'radio'
    radio                # para comprobar el valor almacenado
    radio = 20           # otra forma de asignar
    30 -> radio          # otra forma de asignar
    assign ("radio", 40) # otra forma de asignar 
    
    • el operador habitualmente recomendado para asignar en programas es <-
    • el operador «=» se usa también para asignar valores a argumentos de funciones, por lo que su uso puede resultar ambiguo
    • la función assign se usa sobre todo si el nombre de la variable se determina durante la ejecución del programa
  • para conocer qué variables hay definidas en cierto momento

    ls()
    
  • para borrar la definición de una variable se puede usar alguna de estas dos formas

    rm (radio)
    rm (list = "radio")
    
  • si se quieren eliminar todas las variables definidas hasta el momento

    rm (list = ls())
    
  • en principio, los nombres de variables no pueden contener ciertos caracteres, por ejemplo espacios; no es recomendable, pero en caso de necesidad podrían incluirse así:

    > assign("radio exterior", 50)
    > get("radio exterior")
    [1] 50
    
  • ese get permite construir el nombre de la variable al vuelo:

    > radio1 <- 15; radio2 <- 20; radio3 <- 50
    > for (i in 1:3) cat("El radio número", i, "vale", get(paste0("radio",i)), "\n")
    El radio número 1 vale 15 
    El radio número 2 vale 20 
    El radio número 3 vale 50
    
    > generar_muestra <- function (distri, n=1e6) get(paste0("r",distri))(n)
    > summary (generar_muestra("unif"))
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
     0.0000  0.2506  0.5004  0.5003  0.7504  1.0000 
    > summary (generar_muestra("norm"))
         Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
    -5.454608 -0.673935  0.000999  0.000654  0.673568  4.996585 
    

2.3.4. tipos de datos

2.3.4.1. escalares
2.3.4.1.1. especiales
  • NULL
    • valor nulo; se produce cuando no hay otro resultado
  • NA not available
    • se usa en ficheros de datos para indicar que el dato correspondiente está ausente
    • se produce como resultado de operaciones sin sentido, como al intentar trasformar 8798aue98 en un número

      as.numeric("8798aue98")
      
  • NaN not a number
    • se produce como resultado de algunas operaciones matemáticas

      sqrt (-1)    # raíz cuadrada
      log  (-1)    # logaritmo
      
2.3.4.1.2. lógicos o booleanos

TRUE y FALSE

  • resultan de realizar comparaciones

    10 < 15        # TRUE
    10 > 15        # FALSE
    3 == 3         # == igual
    3 != 3         # != distinto
    identical(3,3) # se usa en vez de == cuando se comparan objetos compuestos
    
  • el operador unario «!» sirve para negar

    !TRUE          # da FALSE
    !FALSE         # da TRUE
    
  • los operadores binarios «&» y «|» son respectivamente, la conjunción copulativa («y» lógico) y la disyunción inclusiva («o» lógica)

    TRUE  & TRUE    # da TRUE
    TRUE  & FALSE   # da FALSE
    FALSE & TRUE    # da FALSE
    FALSE & FALSE   # da FALSE
    TRUE  | TRUE    # da TRUE
    TRUE  | FALSE   # da TRUE
    FALSE | TRUE    # da TRUE
    FALSE | FALSE   # da FALSE
    
  • al comenzar la sesión, la variable T vale TRUE y la F vale FALSE, lo que puede resultar cómodo para uso interactivo

    c(T,T,T,T,F,F,F,T,F,T)
    

    se recomienda usar las palabras completas TRUE y FALSE para evitar problemas si se redefinen T ó F

2.3.4.1.3. numéricos
  • enteros: 58 o bien 58L
  • coma deslizante: 102.23
  • notación exponencial: 1e-6
  • complejos: 5+3i (comparar sqrt(-1) y sqrt(-1+0i))
2.3.4.1.4. caracteres
  • "cadena de texto"
  • 'cadena de texto'
  • para obtener la longitud de una cadena:

    nchar ("cadena de texto") # devuelve 15
    
  • para extraer una subcadena: substring (cadena, posición primero, posición último)

    substring ("cadena", 2, 4) # "ade"
    substring ("cadena", 1, 3) # "cad"
    substring ("cadena", 5, 5) # "n"
    substring ("cadena", 2)    # "adena"
    

    si se omite "posición último" se extrae hasta el final

    existe también "substr" pero no permite omitir el tercer argumento

  • para tratar caracteres como números, puede hacer falta retocar la cadena:

    as.numeric ("2.71")
    as.numeric (gsub (",", ".", "3,14")) 
    
  • ojo, porque el primer argumento de 'gsub' es una expresión regular; por ejemplo, esto no funciona bien:

    gsub (".", ",", "3.14")
    

    hay que refinar la instrucción de alguna de estas maneras:

    gsub ("\\.", ",", "3.14")           # se utiliza \ para "escapar" el punto en la expresión regular;
    ## a su vez, la retrobarra está escapada «\\» porque también es un carácter especial en R;
    gsub (".", ",", "3.14", fixed=TRUE) # interpreta la cadena como tal, no como expresión regular
    
  • para dividir una cadena (más adelante se verá qué son vectores y listas)

    strsplit ("cadena de texto", " ") [[1]] # devuelve "cadena" "de" "texto" 
    
2.3.4.2. compuestos
2.3.4.2.1. vectores
  • creación
    • c(10,15,-3)
    • 10:30
    • seq(-4,4,.1)
    • c("uno","dos","tres")
    • v <- 10:40
  • selección de elementos
    • v[10]
    • v[-10]
    • v[c(1,2,4)]
    • v[-c(1,2,4)]
    • se puede seleccionar mediante vectores lógicos

      v > 35
      v [v > 35]
      v [which (v > 35)]   # útil si contiene NA
      
  • todos los escalares son vectores de longitud 1
  • vectores como conjuntos
    • pertenencia

      elemento %in% v
      
    • unión

      union (v1, v2)
      
    • intersección

      intersect (v1, v2)
      
    • diferencia

      setdiff (v1, v2)
      
  • vectores con nombres

    > v <- c(alfa=3,beta=88,gama=-5)
    > v
    alfa beta gama 
       3   88   -5 
    > names (v)
    [1] "alfa" "beta" "gama"
    > names (v) <- c("A","B","C")
    > v
     A  B  C 
     3 88 -5 
    > v["B"]
     B 
    88 
    > w <- c(primero=TRUE,segundo=FALSE)
    > w
    primero segundo 
       TRUE   FALSE 
    > as.numeric(w)  # pierde nombres
    [1] 1 0
    > +w # forma más rápida de mantenerlos: https://stackoverflow.com/questions/37951199/in-r-how-can-i-preserve-the-names-of-a-vector-when-using-as-numeric/37951526
    primero segundo 
          1       0 
    
2.3.4.2.2. matrices
  • m <- matrix (1:9, 3)
    • crear una matriz a partir de un vector
    • se indica el número de filas (3)
    • para indicar el de columnas: matrix (..., ncol = 3)
    • la matriz se rellena por columnas
    • para rellenarla por filas: matrix (..., byrow = TRUE)
  • m[2, 3]
    • extraer el elemento de la segunda fila y tercer columna
    • puede asignarse: m[2,3] <- -8
  • m[1:2, 2:3]
    • extraer submatriz
    • también puede asignarse: m[1:2,2:3] <- 100
  • m[1,]
    • vector con primera fila
  • m[,1]
    • vector con primera columna
  • m[,1,drop=FALSE]
    • matriz con una sola columna
  • t(m); solve(m); det(m); m%*%m
    • t = traspuesta
    • solve = inversa
    • det = determinante
    • %*% = producto matricial
  • cbind (m, m); rbind (m, m)
    • cbind = pegar varias matrices al lado
    • rbind = pegar varias matrices de arriba a abajo
  • como los vectores, las matrices son homogéneas: todos sus elementos son del mismo tipo

    m[1,1] <- "hola"
    print(m)
    
2.3.4.2.3. listas
  • son como vectores pero, en cada celda, pueden contener cualquier objeto:

    l <- list (a=23, b=v, c=m)
    
  • sublistas:

    l[2]
    l[c(1,3)]
    
  • extraer un elemento:

    l[[3]]
    l[[3]][,1,drop=FALSE]
    l[["c"]]
    l$c
    l$c[,1,drop=FALSE]
    
2.3.4.2.4. dataframes
  • parecen matrices, con columnas heterogéneas (como las listas):

    d <- data.frame (x = 1:5, y = c("uno","dos","tres","cuatro","cinco"), z = 11:15)
    d[3,2]     # notación matricial para extraer elemento
    d[3,]      # notación matricial para extraer fila (no hace "drop", sigue siendo un dataframe)
    d[,1]      # notación matricial para extraer columna (hace "drop", es un vector)
    d[[1]]     # notación de lista  para extraer la primera columna (es un vector)
    d[c(1,3)]  # notación de lista  para extraer dos columnas
    d[,c(1,3)] # notación matricial para extraer dos columnas
    d$x        # notación de lista para extraer columna por nombre
    d[["x"]]   # notación de lista para extraer columna por nombre
    

    esta última versión se usa al programar con variables:

    variable <- "x"
    summary(d[[variable]])
    

    selección de casos mediante vectores lógicos:

    d [d$x > 2, ]
    subset (d, x > 2)      # para evitar repetir el nombre del dataframe
    subset (d, x > 2, y:z) # permite también rangos de columnas por nombre
    
  • se pueden pegar verticalmente con rbind

    rbind (d[3:5,], d[1:2,])
    
  • se pueden pegar horizantalmente con cbind

    cbind (d[1:2,], d[3:4,])
    
  • se pueden cruzar usando merge indicando las columnas con identificadores

    D <- data.frame(id = c(1,4,5), grupo = c("A","A","B"))
    merge (d, D, by.x="x", by.y="id")
    merge (d, D, by.x="x", by.y="id", all=TRUE)
    

    esta última versión incluye todos los registros, rellenando con NA en caso necesario

  • los dataframes son visibles desde Rcmdr
2.3.4.2.5. factores
  • implementan variables cualitativas:

    sexo <- c("M","M","H","H","H","M")
    sexo.f <- factor (sexo)
    levels (sexo.f)
    
  • factor genera un factor

    s = c ("M", "M", "M", "H", "M", "H", "H", "HH", "HM")
    f = factor (s)
    
  • un factor se parece a un vector de caracteres, pero no es:

    as.character (f)
    as.numeric (f)
    nchar(s)             # funciona
    nchar(f)             # no
    
  • factor también elimina los niveles sobrantes

    f1 = f[nchar(as.character(f))==1]
    f1 = factor(f1)
    
  • los NA en principio no aparecen como niveles:

    factor(c(1,1,3,NA))
    factor(c(1,1,3,NA),exclude=NULL)
    
2.3.4.2.6. fechas y horas
  • Trasformar cadena en fecha:

    as.Date ("1978-1-31") # 31 de enero de 1978
    
  • Acepta formatos arbitrarios con estas plantillas:

    plantilla representa
    %d día del mes
    %m mes (número)
    %b mes (abreviado)
    %B mes (nombre completo)
    %y año (dos cifras)
    %Y año (cuatro cifras)
    as Date ("31/1/78", format="%d/%m/%y")
    as.Date ("Ene 31, 1978", format="%b %d, %Y")
    
  • Si el ordenador no está en español, para lo anterior habría que ejecutar antes:

    Sys.setlocale ("LC_TIME", "es_ES.UTF-8")
    

    Asimismo, para leer fechas del sistema operativo (en idioma POSIX o C) podría hacerse así:

    Sys.setlocale ("LC_TIME", "C")
    as.Date ("Jan 31, 1978", format="%b %d, %Y")
    
  • Las fechas pueden restarse, o se les puede sumar o restar un entero.

    as.Date ("1978-1-31") - as.Date ("1977-1-31") # podría aplicarse "as.numeric"
    as.Date ("1978-1-31") + 1
    
  • Dada una fecha, el correspondiente día de la semana puede obtenerse con weekdays

    weekdays (as.Date ("1978-1-31"))
    
  • Para pasar cadenas a horas, se usa strptime:

    strptime ("Oct 10 07:44:31", format = "%b %d %H:%M:%S")
    

    Acepta plantillas %H, %M y %S para horas minutos y segundo. Para otras, véase la ayuda de strptime.

2.3.5. gráficos

2.3.5.1. plot
  • ejemplo
    • sea \(X\sim\mathcal B(n=10,p=0.7)\) y sea una muestra x <- rbinom (100, 10, 0.7)
    • sea \( Y_i \sim\mathcal P(\lambda=x_i) \) y sea y <- rpois (100, x)
  • secuencias

    plot (x)
    plot (x, type = "p") # puntos
    plot (x, type = "l") # líneas
    plot (x, type = "b") # ambos (both)
    plot (x, type = "h") # «histograma»
    
  • gráfico de dispersión de y sobre x

    plot (x, y)
    plot (y ~ x)               # «fórmula»
    plot (y ~ x, datos)        # si «x» y «y» en dataframe «datos»
    with (datos, plot (y ~ x)) # idem
    
  • gráfico de una función en un intervalo

    plot (sin, -pi, pi)
    
2.3.5.2. boxplot, hist, barplot, pie
  • cajas

    boxplot(x)
    
  • histograma

    hist(x)
    
  • tallos y hojas

    stem(x)
    
  • barras y sectores

    barplot(table(x))
    pie(table(x))
    
2.3.5.3. abline, lines, points, text

Para añadir elementos a gráficos ya creados mediante plot, etc.:

  • recta \(y=a+b\cdot x\)

    abline(a,b)
    

    Por ejemplo:

    plot (y ~ x)
    abline (lm (y ~ x), col=2, lwd=3) # col = color; lwd = anchura de la recta
    
  • lines (x, y) para añadir líneas
  • points (x, y) para añadir puntos
  • text (x, y, etiquetas) para añadir textos
2.3.5.4. png

Para que los gráficos vayan a un fichero pixelado. Por ejemplo:

png()
plot(y~x)
plot(x~y)
dev.off()    # para que cierre correctamente los ficheros .png
2.3.5.5. pdf

Para que los gráficos vaya a un fichero vectorial.

pdf()              # mete todos los gráficos subsiguientes en Rplots.pdf
pdf(onefile=FALSE) # crea un .pdf por cada gráfica

Hay que terminar usando dev.off() al igual que con png()

2.3.5.6. dev.off()

Sirve para que los gráficos se cierren correctamente. Si no se usase, podrían quedar operaciones pendiente y el gráfico podría estar sin terminar.

2.3.5.7. savePlot

Para guardar un gráfico ya expuesto en una ventana.

savePlot()

2.3.6. modelos

Consultar el capítulo 11 de Una introducción a R.

  • modelo lineal

    y ~ x
    
  • modelo cuadrático

    y ~ x + I(x^2)
    

2.3.7. generar aleatorios

  • para muestrear se usa sample

    sample (6)                    # permuta números del 1 al 6
    sample (letters)              # permuta un vector arbitrario
    sample (6, 1)                 # 1 tirada de dado hexagonal
    sample (letters, 3)           # tres letras que no se repiten
    sample (6, 10, replace=TRUE)  # 10 tiradas de dado 
    sample (c("M","H"), 100, 
            replace=TRUE, prob=c(.49,.51)) # no equiprobables
    
  • para muestrear de una variable aleatoria, se usan funciones cuyos nombres comienzan por r: rbinom, rexp, rpois, rnorm, runif

    hist (rnorm(10000), breaks=100)
    hist (runif(10000), breaks=100)
    

    (sustituyendo la r inicial por d tendríamos la densidad; por p, tendríamos la función de distribución; por q, la función cuantil)

2.3.8. control

  • condicionales Generemos un vector de temperaturas:

    t <- runif (15, 10, 40)
    

    Para combinar comparaciones vectorialmente, usamos ifelse y un operador «lanzado» («&» = «y»; «|» = «ó»):

    ifelse (t>20 & t<30, "agradable", "desagradable")
    

    Para combinar comparaciones de forma que esperamos un único booleano, usamos operadores «cortocircuito» («&&» = «y»; «||» = «ó»):

    n=10; if (is.numeric(n) && length(n)==1 && n>0) sqrt(n) else "no puedo"
    
  • bloques de instrucciones mediante llaves «{}»; se usan en contextos donde tiene que ir más de una instrucción:

    if (n > 5) {print("demasiado grande"); n<-5} else {print("demasiado pequeño"); n<-n+1}
    

    El valor devuelto por un bloque es el valor devuelto por su última instrucción.

  • bucles

    for (i in 1:10) cat ("El cuadrado de", i, "es", i^2, "\n")
    

    Detrás de «in» puede ir cualquier vector o lista; por ejemplo

    for (i in letters) {cat (i); cat (toupper (i)); cat ("-")}; cat ("\n")
    for (i in iris) print (summary (i))
    
  • bucles con acumulador

    Se define una variable (acumulador) antes del bucle para que recoja los resultados:

    suma <- 0; for (i in 1:10) suma <- suma+i; suma                       # equivale a sum(1:10) -> suma
    producto <- 1; for (i in 1:10) producto <- producto*i; producto       # prod(1:10); factorial(10) -> producto
    bector <- c(); for (i in 1:10) bector <- c(bector,i^2); bector        # (1:10) ^ 2 -> bector
    lista <- list(); for (i in 1:10) lista <- c(lista,list(1:i)); lista   # sapply (1:10, function (i) 1:i) -> lista
    

2.3.9. funciones

  • con nombre

    f <- function(x) x^2
    f(15)
    
  • anónimas (útiles para definiciones al vuelo, como se ve en la sección siguiente)

    (function(x) x^2) (15)
    
  • pueden tener varios argumentos

    var.ponderada <- function (x, pesos)     # varianza ponderada
    {  mp <- weighted.mean (x, pesos)        # media ponderada
       weighted.mean ((x - mp) ^ 2, pesos) }
    
  • cada argumento puede tener un valor por omisión

    var.ponderada <- function (x, pesos = rep(1,length(x)))
    {  mp <- weighted.mean (x, pesos)
       weighted.mean ((x - mp) ^ 2, pesos) }
    
  • pueden pasar sus argumentos a otras funciones mediante «…»

    var.ponderada <- function (x, pesos, ...)
    {  mp <- weighted.mean (x, pesos, ...)
       weighted.mean ((x - mp) ^ 2, pesos, ...) }
    

    por ejemplo:

    muestra <- c (1, 20, NA, 5); pesos <- c (1,2,3,4)
    weighted.mean (muestra, pesos); 
    weighted.mean (muestra, pesos, na.rm=TRUE)
    var.ponderada (muestra, pesos)                  # produce NA
    var.ponderada (muestra, pesos, na.rm=TRUE)      # pasa «na.rm=TRUE» a weighted.mean
    
  • recursivas: una función puede llamarse a sí misma

    mifactorial <- function(n) if (n==0) 1 else n*mifactorial(n-1)
    

    otro ejemplo:

    nombres <- c("Señor don Manuel Montenegro", "Asun Lubiano", "Doña Antonia Salas",
                 "Don Norberto Corral", "Carlos Carleos")
    títulos <- c("don", "doña", "señor", "señora")
    
    ## dado un vector de nombres, obtener el nombre de pila (una palabra) de cada uno
    nombre.de.pila <- function(cadena)
        nombre.de.pila_vector (strsplit (cadena, " ") [[1]]) # convierte "cadena" en vector de palabras
    
    nombre.de.pila_vector <- function(v)    # v = vector de cadenas
    {
        palabra1 <- v[1]
        if (tolower(palabra1) %in% títulos) # tolower = convierte a minúsculas
          nombre.de.pila_vector(v[-1])      # llamada recursiva
        else palabra1
    }
    
    for (nombre in nombres) print (nombre.de.pila (nombre))
    

2.3.10. paquetes

  • las definiciones de variables pueden no estar disponibles en la instalación básica de R, pero sí en bibliotecas o paquetes
  • para ver qué paquetes están instalados:

    installed.packages ()
    
  • para usar una función definida en un paquete:

    e1071::skewness (rexp (10))
    

    o bien

    library (e1071)             # o library("e1071")
    skewness (rexp (10))
    
  • para instalar un paquete no instalado:

    install.packages ("primes")
    primes::is_prime (101)      # sólo funciona si "primes" está instalado
    
  • para actualizar todos los paquetes instalados:

    update.packages (ask = FALSE)
    

2.3.11. bucles sobre estructuras

  • sobre secuencias (vectores o listas)
    • sapply (con s de simple) se usa para generar un vector (o una matriz, si el resultado de la función aplicada es vectorial)

      sapply (1:10, sqrt)                       # aplicar una función con nombre
      sapply (1:10, function(x) x**2)           # aplicar una función anónima
      sapply (1:10, function(x) c(x^2,x^3))     # el resultado es una matriz
      
    • sapply conserva etiquetas si se aplica a un vector de cadenas

      sapply(3:5, sqrt)                         # sin etiquetas
      sapply(c("uno","dos","tres"), nchar)      # con etiquetas
      structure (sapply(3:5, sqrt), names=3:5)  # forzar etiquetas
      
    • lapply (con l de lista) devuelve una lista

      lapply (1:10, function(i) list (i, list(letters[i],month.name[i])))
      

      aunque si se quieren conservar etiquetas mejor usar sapply o (si hace falta) sapply(..., simplify=FALSE)

      lapply (c ("uno", "dos", "tres"), nchar)
      sapply (c ("uno", "dos", "tres"), nchar)
      sapply (c ("uno", "dos", "tres"), nchar, simplify=FALSE)
      
  • apply se usa para aplicar una función a filas o columnas de una matriz…

    m <- matrix (1:12, 3)
    apply (m, 1, sum)                 # aplicar por filas
    apply (m, 2, sum)                 # aplicar por columnas
    

    …o a un dataframe; en este caso, téngase en cuentra que se trasforma en matriz (homogénea) antes de aplicarse la función, por lo que (por ejemplo) si el dataframe contiene un factor todos los datos aparecen como cadenas:

    ## queremos trasformar todos los 4 de ChickWeight a NA
    ChickWeight
    cuatroNA <- function (x) {x[x==4] <- NA; x}
    cuatroNA (1:10)                                       # funciona
    cuatroNA (as.character (1:10))                        # funciona
    cuatroNA (factor (1:10))                              # funciona
    summary (apply (ChickWeight, 2, cuatroNA))            # apply no funciona (trasforma todo a factores)
    summary (data.frame (lapply (ChickWeight, cuatroNA))) # lapply sí funciona
    

    es decir, cuando queremos aplicar una función a cada variable de un dataframe,

    • es mejor considerar el dataframe como lista y usar lapply
    • que considerar el dataframe como matriz y usar apply

    otro ejemplo usando la función identity; identity(x) devuelve x

    mtcars
    apply(mtcars, 1, identity) # queda traspuesta
    apply(mtcars, 2, identity)
    identical(mtcars, data.frame (apply (mtcars, 2, identity))) # TRUE
    m    <- mtcars
    m$am <- factor(m$am)
    apply(m, 1, identity) # genera matrices de cadenas
    apply(m, 2, identity) # idem
    identical(m, data.frame (apply (m, 2, identity))) # FALSE
    
  • para aplicar por grupos:

    prod <- 1:20; sexo <- rep(c("M","H"),each=10)
    tapply (prod, sexo, mean)           # por niveles de "sexo"
    by (prod, sexo, mean)               # ídem
    
  • la más general (mapeo)

    mapply (rep, 1:4, 4:1)              # aplica funciones con varios argumentos
    
  • un comando muy habitual en simulaciones:

    replicate (10000, {m <- rnorm(5); mean(m)})
    

    Funciona parecido a

    sapply (1:10000, function (i) {m <- rnorm(5); mean(m)})
    

    donde la variable i es sintácticamente necesaria pero su valor no se usa.

2.3.12. medir tiempos de ejecución

En general, nos interesará el indicado como «elapsed».

2.3.12.1. system.time

Se encierran las instrucciones dentro de una llamada a system.time:

> system.time ({Sys.sleep(5); Sys.sleep(5)})
   user  system elapsed 
   0.00    0.00   10.01 
2.3.12.2. proc.time

Se llama a proc.time antes y después de la ejecución, y se restan los valores:

comienzo <- proc.time ()
Sys.sleep(5)
Sys.sleep(5)
final <- proc.time ()
final - comienzo

2.3.13. manejo de errores, avisos y datos ausentes

2.3.13.1. try

Sobre todo a la hora de realizar bucles, podemos encontrar molesto que la ocurrencia de un error en una iteración implique la pérdida de los cálculos de las demás iteraciones. Para evitarlo se puede usar try :

sapply (c(3,2,1,0,1,2), function(x) if (x) 10*x else no.existo)
sapply (c(3,2,1,0,1,2), function(x) try (if (x) 10*x else no.existo))

Para aprovechar los resultados, puede ser necesario usar «as.numeric»:

as.numeric (sapply (c(3,2,1,0,1,2), function(x) try (if (x) 10*x else no.existo)))
2.3.13.2. depurar mediante browser

Si en la definición de una función incluimos una llamada a browser(), entramos en el depurador y podemos:

  • evaluar expresiones, incluyendo variables locales
  • ejecutar paso a paso con la orden n (next)
  • continuar con la ejecución mediante c
  • interrumpir la ejecución mediante Q (quit)

He aquí un ejemplo de sesión, en la que se define una función para calcular el coefciente de variación:

> coef.var <- function (x) {media <- mean(x); dt <- sd(x); dt/media}
> muestra <- c(0, -9, 5, 0, 4)
> coef.var (muestra)
[1] Inf
> coef.var <- function (x) {browser(); media <- mean(x); dt <- sd(x); dt/media}
> coef.var (muestra)
Called from: coef.var(muestra)
Browse[1]> debug en #1: media <- mean(x)
Browse[2]> n
debug en #1: dt <- sd(x)
Browse[2]> media
[1] 0
Browse[2]> n
debug en #1: dt/media
Browse[2]> dt
[1] 5.522681
Browse[2]> c
[1] Inf
> 

Hemos explorado qué valores toman dt y media dentro de la función, de forma que comprobamos in situ que se realiza una división por cero.

2.3.13.3. suppressWarnings

Si queremos evitar avisos que prevemos, podemos usar suppressWarnings :

edad <- c("15", "62", "no desvela su edad", "48", "no contesta")
as.numeric (edad)
suppressWarnings (as.numeric (edad))

Puede interesar también la opción «silent=TRUE» de try.

2.3.13.4. na.action

Para usar ciertas funciones es aconsejable cambiar el comportamiento habitual de R con los NA (datos ausentes). Por ejemplo, podemos tener interés en incorporar a los datos originales las puntuaciones (scores) resultantes de un análsisis de componentes principales:

options ("na.action")       # na.omit por omisión

## ejemplo de ?na.omit ?na.exclude
DF <- data.frame(x = c(1, 2, 3), y = c(0, 10, NA))
na.omit(DF)
p <- princomp (~ x + y, DF) # análisis de componentes principales
p$scores                    # sólo para dos individuos

options (na.action = na.exclude)
p <- princomp (~ x + y, DF) # ACP, lo mismo que antes
p$scores                    # también para el tercero (aunque tenga NA)
DF$acp1 <- p$scores[,1]     # lo que permite pegarlo al dataframe original

La interfaz Rcmdr efectúa esa acción de forma predeterminada.

La asignación de opciones puede hacerse de varias formas:

options (na.action   = na.exclude)   # se asigna una función
options (na.action   = "na.exclude") # se asigna una cadena con el nombre de la función
options ("na.action" = na.exclude)   # el nombre de la opción puede estar entrecomillado
options ("na.action" = "na.exclude")

El resultado de cada asignación puede comprobarse con

options ("na.action")
options()$na.action       # mismo efecto

pero

options (na.action)

da error, porque los argumentos de "options" han de ser cadenas (con el nombre de las opciones) o parejas de la forma: etiqueta = valor.

2.3.14. expresiones regulares (regexp)

Para manejar cadenas de texto.

Las expresiones regulares interpretan algunos caracteres de forma especial.

  • ^ = comienzo de cadena
  • $ = fin de cadena
  • [ ] = grupo de caracteres
  • . = cualquier carácter
  • * = cero o más repeticiones
  • + = una o más repeticiones
  • \ = quita el comportamiento especial a un carácter

Hay más referencias en la wikipedia.

2.3.14.1. coincidencia exacta
v <- c("Villa","Luanco","Villaviciosa","Candás","Pendones","Villa","Veranes")
which (v=="Villa")              # devuelve posiciones de todos
match ("Villa", v)              # devuelve posición del primero
grep ("^Villa$", v)             # devuelve posiciones de todos
grep ("^Villa$", v, value=TRUE) # devuelve todas las cadenas congruentes
2.3.14.2. coincidencia con una parte
grep ("Villa", v)               # posiciones de cada cadena que contiene Villa
grep ("Villa", v, value=TRUE)   # devuelve valores
grep ("c", v, ignore.case=TRUE) # contienen «c» mayúscula o minúscula
grep ("^V", v)                  # empiezan por «V»
grep ("s$", v)                  # terminan por «s»
2.3.14.3. coincidencia con patrones más genéricos
grep ("[aeiou]",  letters) # las vocales
grep ("[^aeiou]", letters) # las consonantes (el circunflejo niega)
grep ("[a-dx-z]", letters) # las cuatro primeras letras o las tres últimas
grep ("^V.*a$", v)         # empieza por «V» y acaba en «a»

ficheros <- system ("ls -a ~", intern=TRUE) # todos los de la carpeta personal
grep ("^\\.", ficheros, value=TRUE)         # ficheros ocultos; empiezan por .

En este último caso,

  • grep ("^.", ...) no funcionaría porque . se refiere a cualquier carácter
  • grep ("^.", ..., fixed=TRUE) no funcionaría porque fixed=TRUE impediría el significado especial de ^
  • grep (".", ..., fixed=TRUE) no funcionaría porque incluiría ficheros no ocultos cuyo nombre contiene un punto
  • grep ("^\.", ...) no funcionaría porque \ es el «carácter de escape» de las cadenas de R, y \. no es una secuencia de escape reconocida
  • grep ("^\\.", ...) funciona porque la cadena ^\\. es la representación externa en R de la cadena interna ^\.:

    > nchar ("^\\.")
    [1] 3
    > substr ("^\\.", 1,1)
    [1] "^"
    > substr ("^\\.", 2,2)
    [1] "\\"
    > substr ("^\\.", 3,3)
    [1] "."
    

2.3.15. funciones genéricas (orientación a objetos)

  • la instalación básica de R contiene dos sistemas de objetos
    • el llamado S3, que comentaremos en esta sección
    • el llamado S4, un sistema más formal pero no tan extendido como S3; no lo detallaremos
  • características de un sistema orientado a objetos
    • polimorfismo: una función se comporta de manera distinta en función de su argumento

      summary (mtcars $ am)              # el argumento es un vector numérico => media y 5 cuartiles
      summary (factor (mtcars $ am))     # el argumento es un factor => tabla de frecuencias absolutas
      
    • clase: el tipo de objeto

      class (mtcars $ am)              # el argumento es un vector numérico
      class (factor (mtcars $ am))     # el argumento es un factor
      
    • función genérica: una función que acepta argumentos de distintas clases y se comporta de forma distinta según la clase; por ejemplo, summary
    • método: implementación de una función genérica para cierta clase de argumentos

      methods (summary)                  # qué metodos hay definidos para "summary"
      summary.factor                     # implementación para factores
      summary.default                    # implementación por omisión, p.ej. para vectores numéricos
      summary.lm                         # implementación para modelos lineales
      summary.ecdf                       # error porque está indicado con * al ejecutar "methods(summary)"
      getAnywhere (summary.ecdf)         # forzamos la obtención del código fuente de dicho método
      
  • objetos S3 en R
    • para estudiar el tipo de un objeto, se usan class y mode

      m <- matrix (1:12, 3)
      class (m)                            # matrix
      mode  (m)                            # integer
      class (mtcars)                       # data.frame
      mode  (mtcars)                       # list
      class (1:5)                          # integer
      class (sum)                          # function
      class (function (x) x^2)             # function
      class (by(mtcars$mpg,mtcars$am,mean) # by
      
    • a un objeto de R se le pueden asociar atributos

      ob <- 1:5
      attributes(ob)                       # NULL
      attr(ob,"creador") <- "carlos"  
      ob
      attributes(ob)
      attributes(ob)$creador
      100 * ob                             # el objeto sigue comportándose normalmente
      
    • si un objeto tiene un atributo llamado class entonces ése determina su clase

      efe <- factor (c ("a", "a", "b"))
      efe
      attributes (efe)                     # levels y class
      unclass (efe)                        # un vector numérico
      

      a veces puede interesar deshacerse de la clase

      resumen  <- with (mtcars, by (wt, list(AM=am,VS=vs), median))
      resumenA <- unclass (resumen)              # conseguimos una matriz
      attr(resumenA,"call") <- NULL              # eliminamos atributos sobrantes
      
    • podemos inventar nuevas clases y definir métodos para ellas

      efe <- rbinom (10, 5, 0.3)
      class(efe)  <- "cuandiscreta"           # cuantitativa discreta
      attributes(efe)                         # class
      print.cuandiscreta <- function (x)
          print (factor (x))                  # se muestran los niveles...
      
      efe                                     # aplica el me'todo "print"
      efe * 100                               # pero puede usarse numéricamente
      
      summary.cuandiscreta <- function (x)
      {
          cat ("Cuantitativamente:\n")
          print (summary (as.numeric (x)))
          cat ("Discretamente:\n")
          print (summary (factor (x)))
      }
      
      summary (efe)                           # me'todo "summary"
      
  • ejercicios
    • modificar el método summary de cuandiscreta para que dé también porcentajes
    • crear un método de la función plot que sea adecuado para cuandiscreta

3. SED, AWK, MLR

3.1. sed

  • sed = stream editor
  • función más importante: sustituir cadenas
  • ejemplo 1:

    En el fichero vacas.csv disponemos de dos tipos de valores que indican ausencia de dato: la cadena vacía y el cero.

    Veamos que existen campos vacíos:

    cat vacas.csv | grep ';;' | head
    

    Veamos que existen campos con cero:

    cat vacas.csv | grep ';0;' | head
    

    Para no tener que andar diciendo a R que 0 indica ausente, vamos a eliminar los campos con cero:

    cat vacas.csv | grep ';0;' | head | sed 's/;0;/;;/g'
    

    El comando sed usa s/ORIGINAL/SUSTITUTO/ para remplazar. La g final indica que el cambio el global, es decir, se hace siempre que se encuentra ORIGINAL, no sólo la primera vez. Pero hay un problema. En la secuencia ;0;0;, la primera vez sustituye ;0; por ;;, con lo que la cadena queda ;;0;. Sin embargo, la segunda vez que busca ;0; empieza a hacerlo tras el segundo punto y coma, por lo que no encuentra ;0; y deja el segundo cero sin quitar. Probemos a repetir el proceso:

    cat vacas.csv | grep ';0;' | head | sed 's/;0;/;;/g' | sed 's/;0;/;;/g'
    

    Parece que ahora sí va. Hagamos el cambio permanente:

    cat vacas.csv | sed 's/;0;/;;/g' | sed 's/;0;/;;/g' > vacas-sin-0.csv
    
  • ejemplo 2:

    En ese mismo fichero vacas.csv, las fechas vienen con formato día/mes/año, lo que es un poco engorroso para leer en R, ya que as.Date usa por omisión el orden año/mes/día y tendríamos que usar su opción format. Vamos a preprocesar el fichero con sed para reordenar los elementos de las fechas.

    Las siguientes cuatro instrucciones hacen lo mismo:

    head vacas.csv | sed 's#\(..\)/\(..\)/\(....\)#\3/\2/\1#g'
    head vacas.csv | sed 's#\(.\{2\}\)/\(.\{2\}\)/\(.\{4\}\)#\3/\2/\1#g'
    head vacas.csv | sed -r 's#(.{2})/(.{2})/(.{4})#\3/\2/\1#g'
    head vacas.csv | sed -r 's#(..)/(..)/(....)#\3/\2/\1#g'
    
    • Todas ellas usan el carácter # en vez de / para no provocar confusión porque éste se usa en las fechas. Tras el comando s de sed se puede usar cualquier carácter.
    • Las dos primeras usan el conjunto de caracteres especiales por omisión:
      • Es especial el punto "." que representa a cualquier carácter.
      • Las secuencias \1, \2 y \3 representan los caracteres encontrados asociados a los paréntesis escapados \( y \)
      • Los paréntesis y las llaves no son especiales, por eso se escapan con \
    • Las dos últimas usan el conjunto de caracteres especiales ampliado (por la opción -r), lo que aclara un poco la instrucción:
      • Ahora son especiales tanto el punto "." como los paréntesis () y las llaves {}
    • Las instrucciones primera y cuarta representan dos dígitos mediante ".." y cuatro dígitos mediante "…."
    • Las instrucciones segunda y tercera representan dos dígitos mediante ".{2}" y cuatro mediante ".{4}"

3.2. awk

  • AWK es un lenguaje de programación para manejar ficheros de texto
  • Los programas de AWK tienen la forma:

    awk 'BEGIN{instrucciones}(condición){instrucción1;instrucción2;...}END{instrucción}' fichero.txt
    

    aunque casi todo es opcional.

  • Por cada renglón, $0 representa el renglón completo, $1 el primer campo, $2$ el segundo, etc.
  • Para indicar un separador de campos, se usa la opción -F (similar a la -d de cut):

    head vacas.csv | cut -d';' -f2
    head vacas.csv | awk -F';' '{print $2}'
    
  • Si no se indica separador, toma como separador cualquier cantidad de blanco (espacios o tabuladores), lo que no hace directamente cut. Por ejemplo, para extraer las alzadas de vacas.txt:

    awk '{print $4}' vacas.txt | tee alzadas.txt | head
    

    o bien, para quedarnos sólo con las estrictamente positivas:

    awk '($4>0){print $4}' vacas.txt | tee alzadas.txt | head
    
  • Ejemplo de cálculo de media de "alzada" en "vacas.txt":

    awk 'BEGIN{n=0; suma=0} ($4>0 && $4<300) {n = n+1; suma = suma+$4} END{print n, suma/n}' vacas.txt
    

    Lo anterior es equivalente a

    awk '($4>0&&$4<999){n++;suma+=$4}END{print n,suma/n}' vacas.txt
    
  • AWK establece una serie de variables como NR (número de registro) y NF (número de campos):

    awk '{print NR,NF}' vacas.txt  
    awk -F';' '{print NR,NF}' vacas.csv
    

3.3. mlr (miller)

sudo apt install miller
man mlr

Facilita el uso de ficheros CSV que dispongan de renglón de cabecera con nombres de las columnas. Por ejemplo:

carleos@bellman:~/datos$ head -n1 vacas.csv
nomMunicipio;f_nacim;f_destete;alzada;long_cruz;ancho_muslos;curva_nalga;peri_torax;peso;sexo;tipo

carleos@bellman:~/datos$ awk -F';' '{print $4,$9}' vacas.csv | head
alzada peso
94 175
104 253
0 190
106 218
106 262
102 213
0 160
100 161
100 199
carleos@bellman:~/datos$ mlr --csvlite --fs semicolon cut -f alzada,peso vacas.csv | head
alzada;peso
94;175
104;253
0;190
106;218
106;262
102;213
0;160
100;161
100;199
carleos@bellman:~/public_html/master/manadine/curso1/TIplE/ejercicios/datos$

Cuando se trabaja con ficheros muy grandes, mlr es bastante menos eficiente que awk o los comandos cut, join… de GNU Coreutils.

3.4. datamash

sudo apt install datamash
info datamash

Implementa operaciones estadísticas diversas para aplicar a ficheros CSV, con o sin renglón de cabecera.

3.5. tabla resumen

tratamiento de ficheros de datos textuales tabulares

tipo: delimitador único anchura fija delimitador repetido
ejemplos csv censo I.N.E. vacas.txt
  tsv    
Bash cut -f -d cut -c awk
  awk -F    
R read.csv read.fwf read.table
  read.csv2    
  read.delim    
  read.delim2    

4. otros lenguajes

4.1. generalistas

4.1.1. interpretados ("a alto nivel")

  • "cómodos" para programar
    • con poco código fuente se hacen muchas cosas
  • en general, poco eficientes
    • aunque para cosas concretas pueden usar bibliotecas escritas en lenguajes compilados
4.1.1.1. perl
  • Perl 4 era una especie de AWK "a lo grande"
  • de hecho, existe a2p = "AWK to PERL":

    echo '{n++;suma+=$4}END{print suma/n}' | a2p
    
  • Perl 5
    • muy extendido
    • CPAN - gran biblioteca
    • PDL - para matemáticas
    • Bioperl - para bancos de datos "ómicos"
  • Perl 6
    • poco éxito
4.1.1.2. python
  • ha ocupado nichos tradicionales de Perl
    • administración de sistemas
    • interfase a bibliotecas en C/Fortran
  • ha ocupado nuevos nichos
    • informática empotrada (móviles, vestibles…)
    • redes sociales
  • sintaxis "clara"
    • estructura por sangría en vez de llaves

4.1.2. compilados ("a bajo nivel")

  • más "incómodos": hay que escribir mucho código para hacer lo básico
4.1.2.1. c / c++ / java
  • muy extendidos → muchísimas bibliotecas
  • compiladores optimizados → código objeto muy rápido
4.1.2.2. fortran
  • tradición en matemáticas
4.1.2.2.1. 77
  • muchas bibliotecas clásicas
4.1.2.2.2. 95
  • sintaxis mucho más cómoda
    • saltos y bucles
    • aritmética vectorial/matricial
4.1.2.2.3. 2008
  • lenguaje "moderno"
    • interopera con C
    • unicode
    • paralelismo

4.1.3. lisp ("a alto y a bajo nivel")

  • sintaxis "sencilla"

    • casi sin sintaxis
    (función arg1 arg2 ... argN)    # para todo
    (+ 3 5 6 (/ 9 2) (/ 5) (* 1 (- 1 2)))
    (+ 3 
       5 
       6 
       (/ 9 2) 
       (/ 5) 
       (* 1 
          (- 1 2)))
    (dolist (i lista) (print (elt lista i)))
    (if (< 0 x 20) 
        (print "dentro de límites")
        (print "fuera")
    
    • editores de texto permiten navegar el código fuente como un árbol
    • código fuente procesable fácilmente como datos
  • permite generar código muy eficiente
  • macros: permiten programar a muy alto nivel
4.1.3.1. common lisp
  • "industrial"
  • estándar enorme
  • compilador más eficiente: SBCL
4.1.3.2. scheme
  • "académico"
4.1.3.2.1. racket
  • muchas bibliotecas
  • entorno de desarrollo muy amigable
4.1.3.2.2. guile
  • usado profusamente en GNU
    • shepherd: gestión de servicios (demonios)
    • guix: gestor de paquetes
    • gdb: depurador de C/Fortran…
    • gnucash: contabilidad
4.1.3.3. clojure
  • paralelismo / concurrencia
  • programación genética (pushgp)
  • incanter para estadística

4.2. matemáticos

4.2.1. octave

  • sintaxis de Matlab
  • más cómodo que R para lo básico
    • menos paréntesis
    • menos llaves
  • más incómodo para programas largos
    • sintaxis más irregular, menos predecible
  • más lento que R

4.2.2. julia

  • sintaxis similar a Octave
  • compilado: más rápido que R

4.2.3. maxima

  • cálculo simbólico

Notas al pie de página:

1

Para descargar todos a la vez puedes usar los comandos wget o curl. (Ahora pulsa "b" para volver atrás.)

2

…si va separada por un espacio de lo anterior.

3

La ruta de la papelera personal es ~/.local/share/Trash/files

Autor: Carlos Enrique Carleos Artime

Created: 2024-10-17 jue 15:49

Validate