Técnicas Informáticas para la Estadística
Índice
- 1. Ubuntu
- 1.1. aula B03
- 1.2. instalación
- 1.3. informática libre
- 1.4. plataforma / arquitectura
- 1.5. sistema operativo
- 1.6. capas
- 1.7. terminales virtuales y sistema gráfico
- 1.8. jerarquía de directorios
- 1.9. Introducción a la «línea de comandos»
- 2. R
- 2.1. Instalación
- 2.2. Interfaces
- 2.3. Lenguaje
- 2.3.1. ayuda
- 2.3.2. comentarios
- 2.3.3. variables
- 2.3.4. tipos de datos
- 2.3.5. gráficos
- 2.3.6. modelos
- 2.3.7. generar aleatorios
- 2.3.8. control
- 2.3.9. funciones
- 2.3.10. paquetes
- 2.3.11. bucles sobre estructuras
- 2.3.12. medir tiempos de ejecución
- 2.3.13. manejo de errores, avisos y datos ausentes
- 2.3.14. expresiones regulares (regexp)
- 2.3.15. funciones genéricas (orientación a objetos)
- 3. SED, AWK, MLR
- 4. otros lenguajes
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)
- 10 segundos para elegir
- MANADINE-01, MANADINE-04 y MANADINE-12 tienen Ubuntu a través de GRUB y Windows en VirtualBox
- dejar que arranque GRUB (tras tres segundo inicia Ubuntu)
- el gestor de cuentas de usuario (GDM) permite elegir entre tres:
- Profesor de MANADINE (usuario administrador)
- Estudiante de MANADINE (usuario sin privilegios)
- Windows
- si se escoge Windows: tras apagar Windows y volver a GDM, recuérdese apagar el Ubuntu
- la mayoría tiene arranque dual mediante GRUB:
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:
- GNU: establecimiento de la Free Software Foundation
- Debian: definición de su contrato social
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:
i386
…i686
x86
- PC 64 bit:
amd64
x86_64
- PC 32 bit:
- 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úcleoordenata
= nombre del ordenador en la red3.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úcleox86_64
= nombre de la máquinax86_64
= nombre del tipo de procesadorx86_64
= nombre de la plataformaGNU/Linux
= nombre del sistema operativo
1.5. sistema operativo
algunas referencias:
1.6. capas
1.6.1. linux
1.6.3. apt (debian)
1.6.4. x
- x.org, en Freedesktop
- wayland sustituye a X en las últimas versiones de Ubuntu
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
- página 18 de http://www.malaga.es/subidas/archivos/7/4/arc_143147.pdf
- http://en.flossmanuals.net/command-line/file-structure/
- en el terminal (
q
para salir):man hier
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»
Referencia: Introduction to the command line
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 pulsandoIntro
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
- el navegador de ficheros (p.ej. Nautilus del Gnome en Ubuntu)
- Filezilla
- WinSCP en Windows
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».
- Con GIMP.
- Consigue una imagen. Por ejemplo, descarga una (a la carpeta
Descargas
) con Firefox usando este enlace: imagen - Abre el programa GIMP (o Krita o MyPaint…).
- 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. - Comprueba las diferencias en tamaño de fichero respecto a la imagen original.
- Consigue una imagen. Por ejemplo, descarga una (a la carpeta
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
- Crea una carpeta con el nombre
textos
dentro deDescargas
. - Descarga1 dentro de
textos
los ficheros disponibles en http://bellman.ciencias.uniovi.es/~carleos/master/manadine/curso1/TIplE/ejercicios/datos/textos - 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 Sí 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 Sí.
- 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
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
.- Abrir con: Gestor de archivadores
- Extraer en (por ejemplo)
Escritorio
- Entrar en la carpeta =~/Escritorio/rstudio-0.99.903/bin
- Botón derecho sobre
rstudio
, elegir «Crear un enlace» - Mover el nuevo
Enlace hacia rstudio
alEscritorio
- 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
- el operador habitualmente recomendado para asignar en programas es
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úmeroas.numeric("8798aue98")
NaN
not a numberse 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
valeTRUE
y laF
valeFALSE
, lo que puede resultar cómodo para uso interactivoc(T,T,T,T,F,F,F,T,F,T)
se recomienda usar las palabras completas
TRUE
yFALSE
para evitar problemas si se redefinenT
óF
2.3.4.1.3. numéricos
- enteros:
58
o bien58L
- coma deslizante:
102.23
- notación exponencial:
1e-6
- complejos:
5+3i
(compararsqrt(-1)
ysqrt(-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
= traspuestasolve
= inversadet
= determinante%*%
= producto matricial
cbind (m, m); rbind (m, m)
cbind
= pegar varias matrices al ladorbind
= 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 identificadoresD <- 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 factors = 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 sobrantesf1 = 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
oC
) 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 destrptime
.
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)
- sea \(X\sim\mathcal B(n=10,p=0.7)\) y sea una muestra
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
sobrex
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íneaspoints (x, y)
para añadir puntostext (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 pord
tendríamos la densidad; porp
, tendríamos la función de distribución; porq
, 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
(cons
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 cadenassapply(3:5, sqrt) # sin etiquetas sapply(c("uno","dos","tres"), nchar) # con etiquetas structure (sapply(3:5, sqrt), names=3:5) # forzar etiquetas
lapply
(conl
de lista) devuelve una listalapply (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)
devuelvex
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
- es mejor considerar el dataframe como lista y usar
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áctergrep ("^.", ..., fixed=TRUE)
no funcionaría porquefixed=TRUE
impediría el significado especial de^
grep (".", ..., fixed=TRUE)
no funcionaría porque incluiría ficheros no ocultos cuyo nombre contiene un puntogrep ("^\.", ...)
no funcionaría porque\
es el «carácter de escape» de las cadenas de R, y\.
no es una secuencia de escape reconocidagrep ("^\\.", ...)
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
ymode
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 claseefe <- 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
decuandiscreta
para que dé también porcentajes - crear un método de la función
plot
que sea adecuado paracuandiscreta
- modificar el método
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
usas/ORIGINAL/SUSTITUTO/
para remplazar. Lag
final indica que el cambio el global, es decir, se hace siempre que se encuentraORIGINAL
, 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 queas.Date
usa por omisión el orden año/mes/día y tendríamos que usar su opciónformat
. Vamos a preprocesar el fichero consed
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 comandos
desed
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{}
- Ahora son especiales tanto el punto "." como los paréntesis
- 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}"
- Todas ellas usan el carácter
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
decut
):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) yNF
(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