Archivo de la categoría: Trucos

Ejecutar un código al iniciar la sesión de R

A raíz de una conversación en Twitter os traigo un pequeño truco de R para aquellos que tenéis funciones predefinidas y que tenéis que cargarlas al iniciar las sesiones de R, es como ejecutar el código nada más abrir R. En mi caso el código que quiero ejecutar son una serie de utilidades que tengo guardadas en C:\carpeta, con source(«C:/carpeta/Utils.R», encoding=»UTF-8″) R cargaría todo el código R alojado en ese script de R y necesito que se ejecute el script al inicial la sesión de R, no quiero poner esa línea al principio de cada programa. Lo primero que tenemos que hacer es buscar donde tenemos instalado R, una vez hallamos accedido a la correspondiente carpeta vamos a la subcarpeta /etc y tenemos un archivo llamado Rprofile.site lo abrimos con un editor de texto:

# Things you might want to change

# options(papersize="a4")
# options(editor="notepad")
# options(pager="internal")

# set the default help type
# options(help_type="text")
  options(help_type="html")

# set a site library
# .Library.site <- file.path(chartr("\\", "/", R.home()), "site-library")

# set a CRAN mirror
# local({r <- getOption("repos")
#       r["CRAN"] <- "http://my.local.cran"
#       options(repos=r)})

# Give a fortune cookie, but only to interactive sessions
# (This would need the fortunes package to be installed.)
#  if (interactive()) 
#    fortunes::fortune()

source("C:/carpeta/Utils.R", encoding="UTF-8")

Pues en ese archivo ponemos source("C:/carpeta/Utils.R", encoding="UTF-8") y cada vez que abramos nuestro R, desde RStudio por ejemplo, se ejecutará el script con nuestras utilidades.

Medias ponderadas en Excel. Crear tu propia función

Hace años conocí a una persona que no sabía hacer medias ponderadas con Excel, hoy esa persona es una referencia dentro de este ecosistema de Inteligencia Artificial, Big Data, Machine Learning, Unsupervised Learning,… total, una referencia en la venta de humo porque me imagino que seguirá sin saber hacer una media ponderada en Excel con el SUMAPRODUCTO y por eso realizo esta entrada en homenaje a esas grandes locomotoras que echan humo y más humo pero que ahí siguen. Además también es útil para varias cosas más como:

  • Crear nuestra propia función en Excel
  • Emplear rangos en funciones de Excel
  • Crear sumas acumuladas con un bucle en nuestra función
  • Emplear funciones propias de Excel en nuestra función de visual basic

La función es sencilla y replica la forma habitual de hacer medias ponderadas en Excel con el SUMAPRODUCTO del dato del que deseamos calcular la media por el campo de ponderación dividido por la suma del campo de ponderación:

Public Function MEDIAPONDERADA(Valor As Range, Ponderacion As Range)

 If Valor.Rows.Count <> Ponderacion.Rows.Count Then
 Sample = "Tamaños distintos de rango"
 Exit Function
 
 ElseIf Valor.Rows.Count = 1 Then
 Sample = "Solo un número no se puede"
 Exit Function
 End If

 acum = 0
 For i = 1 To Valor.Rows.Count
   dato = Valor(i) * Ponderacion(i)
   acum = acum + dato
 Next
 
 MEDIAPONDERADA = acum / Excel.WorksheetFunction.Sum(Ponderacion)

End Function

Esta función la ponéis en el libro de macros personal y cuando escribáis =MEDIAPONDERADA ya la tendréis a vuestra disposición en todas las sesiones de Excel. Saludos.

Truco Excel. Producto cartesiano de dos campos

Hacía tiempo que no ponía trucos en Excel y hoy os traigo un truco que puede ser de utilidad cuando tienes que hacer combinaciones. Se trata de realizar el producto cartesiano mediante una macro de Excel, además os pongo el enlace al propio Excel para que podáis rellenar los campos a cruzar. No creo que haga falta describir que es un producto cartesiano de dos campospero de forma resumida se puede decir que es crear el total de pares de esos dos campos, un todos con todos, es útil cuando quieres hacer combinaciones (como ya he dicho). La macro en Visual Basic se podrá hacer mejor, pero a mi se me ha ocurrido hacer un triple bucle, probablemente se pueda hacer con n campos pero si tenéis que realizar productos cartesianos más complejos es preferible que lo hagáis con otra herramienta. El código empleado es este:

Sub ProductoCartesiano()
    
L1 = Range(Range("A2"), Range("A2").End(xlDown)).Rows.Count
L2 = Range(Range("B2"), Range("B2").End(xlDown)).Rows.Count

Cells(1, 4) = Cells(1, 1)
Cells(1, 5) = Cells(1, 2)

i = 2
j = 1


While i <= L1 * L2
While j <= L1
k = 1
While k <= L2

Cells(i, 4) = Cells(j + 1, 1)
Cells(i, 5) = Cells(k + 1, 2)

k = k + 1
If k > L2 Then j = j + 1
i = i + 1

Wend
Wend
Wend
End Sub

Nada emocionante pero tiene su «talento». Si no queréis complicaros la vida directamente podéis descargar del siguiente enlace la hoja del cálculo que realiza este proceso:

Producto_cartesiano_excelV0

Saludos.

Trucos simples para #rstats

En mi cuenta de twitter suelo poner algunos trucos sencillos de R, cosas que me surgen cuando estoy trabajando y que no me cuesta compartir en 2 minutos, por si puedo ayudar a alguien. Me acabo de dar cuenta que de verdad son útiles y que tenerlos en twitter desperdigados es un problema, así que he pensado en recopilarlos en una entrada del blog para que sea más sencillo buscarlos (incluso para mi). Aquí van algunos de esos trucos Seguir leyendo Trucos simples para #rstats

Truco Excel. Transponer una fila en varias columnas con DESREF

Creo que alguna vez me lo han preguntado. Se trata de tranponer en Excel el contenido de una fila en varias columnas, como es habitual (sobre todo si escribo yo) una imagen vale más que mil palabras:

Transponer varias columnas

En este caso se trata de pasar de una fila a 3 columnas por lo que se trata de que la función DESREF tiene que moverse en función del elemento que va a transpone. En este caso empezando desde A1 tenemos que generar un autonumérico para las columnas que se ha de mover de 3 en 3 por lo que multiplicaremos por 3 y sumaremos la columna:

Para el primer elemento: =DESREF($A$1;0;(FILA(A1)-FILA($A$1))*3)
Para el segundo elemento: =DESREF($A$1;0;(FILA(B1)-FILA($A$1))*3+1)
Para el tercer elemento: =DESREF($A$1;0;(FILA(C1)-FILA($A$1))*3+2)

Ya lo veis, se mueve de 3 en 3 la columna 0 el primer elemento la 1 el segundo y el 2 el tercero.

Crear archivo csv desde SAS con Python

Con la librería sas7bdat de Python podemos leer archivos SAS y crear directamente un data frame, es la mejor librería para hacerlo, si la tabla SAS que deseáis leer está comprimida (compress=yes) con pandas no podréis hacerlo. Pero tengo que agradecer a mi compañero Juan que me haya descubierto la función convert_file para pasar directamente el archivo SAS a csv, es más eficiente y parece que consume menos recursos del equipo. La sintaxis es muy sencilla:

import pandas as pd
from sas7bdat import SAS7BDAT

start_time = time.time()
path_file_sas = '/ubicacion/archivo/sas/tabla_SAS.sas7bdat'
path_file_csv = 'ubicacion/archivo/csv/archivo_CSV.csv'
f = SAS7BDAT(path_file_sas)

f.convert_file(path_file_csv, delimiter=',', step_size=10000)

end_time = time.time()
(end_time - start_time) / 60 

La función convert_file realiza el proceso paso a paso, trozo a trozo, chunk to chunk. Si la tarea la realizas con un equipo esto te permite poder seguir usándolo. Me ha parecido un truco útil para poder importar tablas SAS a Python creando primero un csv, podéis agradecer a Juan.

 

Truco Python. Seleccionar o eliminar variables de un data frame en base a un prefijo, sufijo o si contienen un caracter

A la hora de seleccionar las características de un data frame es posible que nos encontremos con la necesidad de seleccionar o eliminar características del data frame y que el nombre de esas características tenga un determinado patrón. Esta labor la podemos realizar mediante selección de elementos en listas, en esta entrada del blog vamos a tener 3 tipos de selecciones:

1. Seleccionar o eliminar aquellas variables que empiezan por un determinado prefijo
2. Seleccionar o eliminar aquellas variables que contienen una cadena de caracteres
3. Seleccionar o eliminar aquellas variables que finalizan con un sufijo

Para ilustrar este trabajo generamos un data frame con datos aleatorios y 10 columnas:

import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(0,100,size=(100, 10)),
columns=['A1','A2','A3','B1','B2','B3','C1','C2','C3','DA'])

El primero de los filtros a realizar es identificar que variables de nuestro data frame contienen el string ‘A’:

col = list(df.columns)
#Filtro 1: Columnas que tienen una A
filtro1 = [col for col in df if col.find('A')>=0]
#Eliminar
df1_drop = df.drop(columns=filtro1)
#Seleccionar
df1_keep = df[filtro1]

Siempre vamos a hacer el mismo proceso, las características de nuestro data frame irán en una lista, después recorremos la lista y seleccionamos aquellos donde el método .find(‘A’) sea mayor o igual a 0, con esto hemos creado una sublista con aquellas características que tienen el string ‘A’ mediante .drop(columns=) eliminamos del data frame los elementos contenidos en una lista Seguir leyendo Truco Python. Seleccionar o eliminar variables de un data frame en base a un prefijo, sufijo o si contienen un caracter

Truco Python. Agrupar variable en función de la frecuencia

Me ha surgido la necesidad de crear una nueva variable en un data frame a partir de la frecuencia de otra, es decir, quedarme con los valores más frecuentes y aplicar una categoría resto para aquellos valores que no estén en los más frecuentes. Para realizar esto se me ha ocurrido la siguiente función en Python:

def agrupa_frecuencia (var_origen, var_destino, df, grupos, valor_otros):
df_grp= df[var_origen].value_counts()
list_grp = list(df_grp.iloc[0:grupos,].index)
df[var_destino] = df[var_origen].map(lambda x: x if x in list_grp else valor_otros, na_action='ignore')

Es una función con más parámetros que líneas, pero necesitamos una variable de origen, una variable de destino que será la que calcularemos, el data frame sobre el que realizamos la tarea, el número de grupos más otro que será el «resto» y dar un valor a ese «resto». La función lo que hace es una tabla de frecuencias ordenada descendentemente con .value_counts() y creamos una lista con el número de grupos que deseamos. Por último mediante lambdas si la variable origen está en la lista generada anteriormente le asignamos el mismo valor, en caso contrario asignamos el valor «resto». Es una programación sencilla, seguramente haya una función específica en sckitlearn para agrupar variables en base a la frecuencia, pero no la he encontrado y he tardado más en buscarla que en hacerla.

Como es habitual os pongo un ejemplo de uso para que podáis ver como funciona:

personas = 1000
grupo = pd.DataFrame(np.random.poisson(15,personas))
grupo['clave']=0
valor = pd.DataFrame(np.random.uniform(100,10000,personas))
valor['clave']=0
df = pd.merge(grupo,valor,on='clave')
del df['clave']
df.columns = ['grupo', 'valor']
df['grupo'].value_counts()

Vemos que grupo crea muchos valores y vamos a agrupar la variable del data frame de forma que los 10 más frecuentes toman su valor y los demás serán un resto:

agrupa_frecuencia('grupo', 'grupo_nuevo', df, 10, 99)
df['grupo_nuevo'].value_counts()

Parece que funciona, si mejoráis, actualizáis o encontráis pegas…

Truco Python. Restar meses con formato YYYYMM

La operación con fechas en meses con el formato YYYYMM es tarea habitual cuando trabajamos con tablas particionadas. De hecho hay una entrada en el blog sobre esto muy popular. Me ha surgido este tema con Python y os pongo la función que he creado:

def dif_mes(d1, d2):
    return (d1//100 - d2//100) * 12 + d1%100 - d2%100 

dif_mes (201812,201709)

Muy sencilla, por si os surge la necesidad.

Preparar nuestros datos para sklearn. Pasar de string a número

Cuando trabajamos con python y sklearn necesitamos que todos los datos que vamos a modelizar sean númericos, si tenemos variables carácter necesitamos previamente transformarlas a números. La forma más rápida para realizar esta tarea es emplear preprocesing de sklearn:

import pandas as pd
dias = {'dia': ['lunes','martes','viernes','miercoles','jueves','martes','miercoles','jueves','lunes']}
dias = pd.DataFrame(dias)
dias

Creamos un data frame a partir de una diccionario que se compone de los días de la semana ahora vamos a codificar las etiquetas con el LabelEncoder de sklearn:

from sklearn import preprocessing
le = preprocessing.LabelEncoder()
le.fit(dias['dia'])

Podemos listar las clases:

list(le.classes_)

Me gustaría destacar que hay que tener especial cuidado con el orden de las codificaciones porque es un orden léxico-gráfico, no va por orden de aparición:

dias = le.transform(dias['dia'])
dias

Ahora ya estamos en disposición de poder emplear sklearn para entrenar nuestro modelo.