Archivos de la categoría Trucos

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 Sigue 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...

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.

Pasando de SAS a R. Primer y ultimo elemento de un campo agrupado de un data frame

Las personas que están acostumbradas a trabajar con SAS emplean mucho los elementos first, last y by, en el blog hay ejemplos al respecto, en R podemos hacer este trabajo con la librería “estrella” dplyr de un modo relativamente sencillo. A continuación se presenta un ejemplo para entender mejor como funciona, creamos un conjunto de datos aleatorio:

id <- rpois(100,20)
mes <- rpois(100,3)+1
importe <- abs(rnorm(100))*100

df <- data.frame(cbind(id,mes,importe))

Tenemos un identificador, una variable mes y un importe y deseamos obtener el menor importe por mes el primer paso a realizar es ordenar el data frame de R por ese identificador, el mes y el importe en orden descendente:

df <- df[with(df,order(id,mes,-importe)),]

Una vez ordenado el data frame de R tenemos que seleccionar el último elemento por id para seleccionar aquellos clientes con menor importe:

library(dplyr)
df_bajo_importe <- df %>% group_by(id) %>% filter(row_number()==n())

Si deseamos seleccionar el mayor importe hacemos lo mismo:

library(dplyr)
df_bajo_importe <- df %>% group_by(id) %>% filter(row_number()==1)

Las funciones group_by unidas a filter(row_number) equivalen a esos first y last de SAS. Saludos.

Truco Python. Reemplazar una cadena de caracteres en los nombres de las columnas de un data frame

Más largo el título de la entrada que la entrada en si misma. Tenemos un conjunto de datos que os podéis descargar de este link que ya es conocido. Os descargáis los datos y creamos un data frame que tiene 10.000 registros y 251 columnas, casi todas se llaman attx y queremos cambiar el nombre a columna_x. Mi sugerencia para hacerlo vía pandas es:

import pandas as pd
df = pd.read_csv('C:\\temp\\wordpress\\au2_10000.csv')
df.head()

df.columns = df.columns.str.replace('att','columna_')
df.head()

Espero que sea de utilidad. Saludos.

Parámetros en las consultas de Hive. Ejemplo con fechas

Soy cinturón blanco de Hive pero aprovecho el blog para mostraros como he añadido unas variables a mi consulta de Hive, en realidad espero que algún alma caritativa me indique alguna forma más elegante. Necesito que mis consultas vayan parametrizadas por fechas que hacen mención a particiones de la tabla, estas particiones no son variables fecha, son string con el formato YYYYMMDD así que es necesario transformar las variables para realizar operaciones con ellas. En este caso tengo una fecha inicio y quiero irme tres meses hacia atrás:

set inicio="20161231";
set f_aux = add_months(from_unixtime(unix_timestamp(${hiveconf:inicio} ,'yyyyMMdd'), 'yyyy-MM-dd'),-3);
set f_mes_menos3 = from_unixtime(unix_timestamp(${hiveconf:f_aux} ,'yyyy-MM-dd'), 'yyyyMMdd');

Con set defino las variables de mi entorno a las que yo referencio como ${hiveconf:variable}, desconozco si hay otra forma mejor de hacerlo y transformo de caracter a fecha con from_unixtime + unix_timestamp para así poder usar la función add_months que no me funcionaba con string. Después deshago el cambio y ya tengo otra variable a partir de la primera, puedo automatizar mis parámetros. ¿Lo estoy haciendo bien?

Truco Excel. Unir todos los libros en una hoja

unir_excel1

Los trucos Excel referentes a la unión de varios libros en uno tienen mucho éxito en esta web, además era necesario crear una versión que uniera de forma horizontal. No es una unión como la pueda hacer Power Query de anexar tablas con cierto sentido teniendo en cuenta el nombre de las columnas y demás, se trata
de unir todas las celdas de un conjunto de libros de forma horizontal en otro libro resultante como ilustra la figura de arriba. Se unirán todos los campos unos encima de otros independientemente de si se llaman igual o no, si queremos anexar tablas es recomendable usar herramientas más específicas. El funcionamiento es muy sencillo pero
lo vamos a ilustrar con imágenes, el primer paso es pulsar directamente el botón y seleccionar los archivos a unir:

unir_excel2

Ahora sólo tenemos que especificar el archivo de destino, puede existir o no, el proceso lo sustituye:

unir_excel3

Y et voilá! Ya tenemos nuestro archivo resultante Sigue leyendo Truco Excel. Unir todos los libros en una hoja