Archivo de la categoría: Formación

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.

Aprende Pyspark sin complicaciones

Hace tiempo un gran data engineer me preparó una máquina virtual para hacer “pinitos” con pyspark y llevaba tiempo pensando en como poder publicar trucos y ejemplos con pyspark sin necesidad de máquinas virtuales y empleando notebooks. Ya he encontrado la mejor manera, los contenedores de docker. Cuanto más profundizo en docker más me gusta trabajar con contenedores y con esta entrada me váis a entender perfectamente.

El primer paso es instalar docker y arrancar el terminal. La idea de docker es ejecutar un contenedor en cualquier máquina independientemente del sistema operativo. Instalar spark en windows es un dolor de cabeza, si disponemos de una máquina virtual con linux es más sencillo, pero imaginad que, con dos líneas de código ya podéis trabajar con un notebook y pyspark, pues eso lo podemos hacer con docker.

Descargado e instalado docker abrimos el terminal de docker y hacemos pull sobre un contenedor, en este caso yo recomiendo:

docker pull jupyter/all-spark-notebook

Estamos descargando contenedores con pyspark y notebook, cuando el proceso haya finalizado (unos 5GB) en el terminal de docker podéis ejecutar:

docker images

Y podréis ver jupyter/all-spark-notebook con lo cual ya tenéis disponible un contenedor con un notebook que nos permite ejecutar pyspark. Ahora tenemos que arrancar el servicio Seguir leyendo Aprende Pyspark sin complicaciones

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.

Libro de R de Carlos Gil

Muchos de los lectores de esta bitácora conocéis https://www.datanalytics.com/ el blog de Carlos Gil. En él ha publicado un libro/manual de R de acceso libre para todos aquellos que necesitéis una guía que abarque desde lo más básico al tratamiento de datos con R pasando por Shiny y análisis estadísticos de esos viejunos tan denostados últimamente.

De todas formas no sé como no deja este mundillo y se dedica plenamente a su faceta hostelera. En palabras de mi hijo: “El mejor brunch de Madrid, un 10”.

Beatifulsoup. Web scraping con Python o como las redes sociales pueden estar cambiando la forma de escribir

Boxplot_BeatifulShop

Desde hace tiempo mis frases son más cortas. Creo que es un problema de las redes sociales, sobre todo twitter, que está cambiando mi comportamiento. Para analizar si esto está pasando se me ha ocurrido analizar la longitud de las frases de este blog desde sus inicios y de paso aprovechar para hacer web scraping con la librería Beatifulshop de Python. La idea es recorrer el blog y calcular la longitud de las frases y representar gráficamente como ha ido evolucionando esa longitud.

Podía haber trabajado directamente con la base de datos de wordpress pero he preferido leer las páginas de la web. Hay un problema, si véis el nombre de las páginas no tiene un orden cronológico, son el nombre de la propia entrada [https://analisisydecision.es/los-bancos-lo-llaman-transformacion-digital-yo-lo-llamo-me-da-miedo-facebook/] pero es cierto que se almacena una vista por mes de las entradas publicadas [https://analisisydecision.es/2017/02/] vamos a emplear esas vistas que no recogen la entrada entera pero si las primeras frases, con estas limitaciones vamos a medir la longitud de las frases.

Luego la analizamos paso a paso pero la función de Python que voy a emplear es:

import pandas as pd
from bs4 import BeautifulSoup
import requests
import re
import time
import string

def extrae (anio, mes):
url = "https://analisisydecision.es/" + anio + "/" + mes + "/"
print (url)
# Realizamos la petición a la web
pagina = requests.get(url)
soup = BeautifulSoup(pagina.content, 'html.parser')
m = str(soup.find_all('p'))
m = BeautifulSoup(m)
m = str(m.get_text())
frases = pd.DataFrame(m.split("."),columns=['frase'])
frases['largo'] =  frases['frase'].str.len()
frases['mes'] = anio + mes
frases['frase'] = frases['frase'].apply(lambda x:''.join([i for i in x if i not in string.punctuation]))
frases = frases.loc[frases.largo>10]
time.sleep(60)
return frases

Os comento paso a paso, a la función le vamos a pasar el mes y el año y esa será la url que lee https://analisisydecision.es/2017/02/ esa es la web sobre la que vamos a hacer el scraping. Vía request obtenemos la web y BeatifulSoup sólo para quedarnos con el contenido en HTML de la web cargada Seguir leyendo Beatifulsoup. Web scraping con Python o como las redes sociales pueden estar cambiando la forma de escribir

Los bancos lo llaman Transformación Digital yo lo llamo me da miedo Facebook

¿Si Facebook prestara dinero? ¿Si Facebook hiciera un banco? Tiene información interesante de nosotros, variables relevantes para cualquier modelo de scoring de crédito y sabe como es tu comunidad de amigos cibernéticos y cuales de ellos podrían avalarte a la hora de conceder un crédito. Además tanto Facebook, como Amazon o Wallapop tienen sus propios medios de pago y Google no tardará en crear su propio banco, unos están creando la economía del futuro y otros no pueden sobrevivir sin programadores en COBOL, entiendo que se quieran transformar aunque a lo mejor no es un tema de captar pasivo y prestar dinero a lo mejor es un tema de relacionar los recursos de las personas.

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.