"Lookup table" en R y en Python

La verdad es que no sé como traducir el término “lookup table”, en fin, vamos al grano.

Supongamos que tengo un factor con 3 niveles o un vector de caracteres con 3 letras únicas y 20 valores.

set.seed(43)
vector_largo <- sample(c("a","b","c"), size = 20, replace = TRUE)
vector_largo
##  [1] "b" "c" "a" "c" "a" "b" "c" "b" "a" "c" "b" "a" "b" "a" "b" "c" "a"
## [18] "a" "a" "a"

Y que en otro sitio tengo un vector “con nombres” dónde tengo el valor que asigno a “a”, “b” y “c”

vector_corto <- c(10,30,-99)
names(vector_corto) <- c("a","b","c")
vector_corto
##   a   b   c 
##  10  30 -99

El tema es sustituir en vector_largo a, b y c por el valor que tienen en vector_corto. Una forma fácil de hacerlo es usar los corchetes [. Normalmente dentro de los corchetes solemos poner una condición o una lista de posiciones tipo vector_largo[c(1,3,5)] que devolvería las posiciones 1,3, y 5, pero veamos que pasa al hacer lo siguiente.

vector_corto[vector_largo]
##   b   c   a   c   a   b   c   b   a   c   b   a   b   a   b   c   a   a 
##  30 -99  10 -99  10  30 -99  30  10 -99  30  10  30  10  30 -99  10  10 
##   a   a 
##  10  10

Al indexar sobre vector_corto (que tiene names) y usar vector_largo como índices obtenemos vector de longitud 20 y que sustituye a,b, c por su valor en la “lookup table” .

Es un truco viejuno pero útil.

Y en Python podría ser de esta forma (acepto correcciones).

import numpy as np
letras = ['a','b','c']
np.random.seed(13)
vector_largo = np.random.choice(letras, 20)
print(vector_largo)
## ['c' 'a' 'c' 'a' 'c' 'c' 'a' 'b' 'a' 'c' 'c' 'a' 'c' 'c' 'c' 'c' 'b' 'b'
##  'c' 'b']
lookup_table = {'a' : 2, 'b': 3, 'c' : 99}

Y usando las maravillosas listas por comprehensión

vector_largo_bis = [lookup_table[elemen] 
                    for elemen in vector_largo 
                    if elemen in lookup_table]
                    
print(vector_largo_bis)
## [99, 2, 99, 2, 99, 99, 2, 3, 2, 99, 99, 2, 99, 99, 99, 99, 3, 3, 99, 3]

A mí me parece más elegante cómo se hace en R, pero también es probable que se pueda hacer de otra forma en Python.

Corrección en python

Un amable lector me comenta que me sobra el if

vector_largo_bis = [lookup_table[elemen] 
                    for elemen in vector_largo ]
                    
print(vector_largo_bis)
## [99, 2, 99, 2, 99, 99, 2, 3, 2, 99, 99, 2, 99, 99, 99, 99, 3, 3, 99, 3]

Aunque el if sería necesario si hay un elemento en vector_largo que no está en lookup_table.

 
comments powered by Disqus