Está en la página 1de 39

Guía de Resolución - Proyecto 4

1. Contexto
En este proyecto aprenderás a utilizar dos herramientas poderosas de la análitica de datos:
Microsoft PowerBI y Google BigQuery. El primero te ayudará a crear visualizaciones claras e
interactivas para presentar tus resultados y conclusiones. El segundo es un motor de bases de
datos creado por Google que te permitirá manejar grandes volúmenes de datos en tan solo
pocos segundos, sin embargo, para interactuar con los datos también necesitarás aprender el
lenguaje más utilizado en el mundo para esto: SQL.

2. Entender el dataset y luego importar los datos


Como siempre, te recomendamos mirar la data en el visor de datos de datos de Kaggle. Son
muchas columnas y no necesariamente necesitarás todas, por lo que lee atentamente las
descripciones de cada columna y toma nota de aquellas que son de tu interés para el análisis.
Para esto te recomendamos usar la pestaña "Column" (ahí aparecen las descripciones
completas 😉) y además seleccionar todas las columnas para que aparezcan en el visor.
Al descargar el archivo del dataset notarás que es un archivo grande (17MB, casi lo mismo que
un video de youtube de 1 min en alta calidad). Esto es porque para este proyecto utilizarás un
dataset más grande que en los anteriores. De hecho, si intentas importar este archivo a Google
Sheet, lo más probable es que te funcione muy lento. Google Sheet es una herramienta muy útil
para la analítica de volúmenes de datos más pequeños. Cuando tenemos que analizar fuentes
de datos más grandes, es donde entra en juego el nuevo lenguaje SQL y el motor de bases de
datos Google Bigquery.

Lo primero que debes hacer es configurar el ambiente de prueba. Si necesitas ayuda puedes
mirar esta sección del curso. Después de crear un proyecto nuevo debes crear un conjunto de
datos:

Y una vez dentro debes crear una tabla dentro del conjunto de datos.
Como puedes ver, un conjunto de datos puede tener más de una tabla. Para este proyecto
trabajarás con una tabla única, sin embargo en futuros proyectos aprenderás a analizar múltiples
tablas de datos.

A diferencia del curso de SQL en Google BigQuery, en donde se trabaja con un dataset público,
para este proyecto contamos con un set de datos está en formato CSV por lo que tenemos que
subirlo a nuestra nueva tabla. En la opción de "Crear tabla desde" seleccionamos "Subir"
nuestro archivo CSV.

En el resto de las configuraciones la que nos interesa es dejar chequeada la opción de


"Detección automática" del esquema.
Si presionas "Crear Tabla" te darás cuenta que aparecerán una serie de errores 😱.

No te preocupes, esto es común al momento de cargar datos que no están limpios o que la
detección automática de esquema no logra identificar. Para forzar a que BigQuery suba nuestro
archivo sin importar los errores que aparezcan vamos a permitir una gran cantidad de errores.
De esta forma aparecerán, al igual que antes, una serie de errores en pantalla pero BigQuery de
todas formas intentará subir el archivo.

ℹ️Puede que BigQuery se demore unos segundos o incluso minutos en crear tu tabla. Al fin y al
cabo son casi 120.000 registros que está subiendo y procesando. Al terminar se mostrará un
mensaje indicando que se creó tu tabla. Cuando eso suceda puedes cerrar la ventana de
configuración.

Con nuestra tabla arriba podemos comenzar a explorarla, mirar la cantidad de filas que tiene, y
entender los tipos de datos de cada columna. Si todo salió bien con la autodetección de
BigQuery, entonces tendrás columnas bien varias: INTEGERS, STRINGS, FLOAT y DATE.

3. Explorar el set de datos con consultas SQL


Es hora de hacer nuestra primera consulta. Intentemos seleccionar las 10 primeras filas y todas
las columnas de nuestros datos. Si miraste con atención el curso de SQL en Google Bigquery, y
en particular la sección 2, podrás retornar estos datos sin problemas:

🤓 Análisis 🤓

Como puedes observar cada fila del dataset es un registro de una reserva. Por ejemplo, la
primera fila corresponde a una reserva en un Resort Hotel que no fue cancelada (is_canceled
= 0) que fue hecha 4 días antes de la llegada del huésped. Sabemos que solo es un huésped
porque adults=1, babies=0 u children=0. La fecha de llegada es el 2 de Noviembre del 2015,
que corresponde a la semana número 45 del año. Los huéspedes se quedaron 1 noche de
semana y 1 noche de fin de semana. El tipo de comida que reservó es Bed and Breakfast (BB)
y es una persona de portugal (PRT) que pagó 25 USD la noche (adr).

¿Puedes hacer un análisis similar con la fila 3?


Muchas veces queremos seleccionar solo algunas columnas, no todas. Este tipo de consultas
son menos demandantes en términos de procesamiento de información y nos entregan solo las
variables (columnas) que necesitamos.

👩‍💻 ¡Ahora es tu turno! Intenta escribir una consulta que genere una tabla con las columnas
hotel, is_canceled, lead_time, arrival_date_year y solo los primeros 7 registros:

¡Buen trabajo!, ahora que conoces como explorar solo las variables que te interesan del
conjunto de datos, también es importante conocer el dominio de estas ya que ayuda a saber qué
valores puede tener dicha variable, para eso usamos el comando DISTINCT.

Por ejemplo, si nos interesa saber qué valores puede tomar la variable (columna) hotel,
escribimos:

SELECT DISTINCT hotel


FROM `proyecto.dataset.tabla`
Podemos ver claramente que los únicos dos valores que adopta la columna son “City Hotel” y
“Resort Hotel”.

👩‍💻 ¡Ahora es tu turno!, ¿podrías indicarnos cuáles son los valores únicos de la variable
"market_segment"? Te recomendamos explorar otras columnas con DISTINCT para conocer
su dominio (valores posibles).

😎 Recuerda que siempre puedes consultar la historia de tus QUERIES o guardar consultas
que te parezcan útiles en BigQuery. Para recordarlo revisa esta sección del curso.

¡Bien hecho! Otra forma útil de explorar los datos es contando registros. Por ejemplo, si
quisiéramos contar cuantas filas tiene todo nuestro dataset podemos correr:

SELECT COUNT(*)
FROM `proyecto.dataset.tabla`

Podemos observar que el conjunto de datos contiene un total de 119,386 registros. La función
COUNT la podemos ocupar en todas las columnas (y por eso el operador * ) como también en
algunas columnas específicas. Para hacer eso escribimos el nombre de la columna dentro del
paréntesis.

Hasta ahora hemos podido aprender comandos que nos permiten visualizar un número
establecido de registros, conocer el dominio de nuestras variables y a su vez cuantificar el
número de registros para cada variable. Pero cuando trabajamos un conjunto de datos no
siempre necesitamos el 100% de los registros, gran parte de los análisis se requiere de filtros
para trabajar con subconjuntos del conjunto de datos. El comando WHERE nos permitirá realizar
los filtros necesarios para obtener el subconjunto requerido.

Supongamos que queremos solamente las reservas realizadas en un City Hotel. Utiliza la
función WHERE para obtener ese resultado:
También podemos filtrar registros haciendo comparaciones con números. Intenta seleccionar
solo las reservas que se han hecho con menos de 3 meses de anticipación (menor o igual a 90
días de lead time).

Podemos encadenar lo que hemos aprendido hasta ahora. Por ejemplo si quisiéramos saber
cuántas reservas se hicieron el 2015 podemos aplicar un filtro con WHERE y luego contar ese
resultado con COUNT. Algo como:

SELECT COUNT(*)
FROM `proyecto.dataset.tabla`
WHERE arrival_date_year = 2015

👩‍💻 ¡Ahora es tu turno!, ¿podrías indicarnos cuántas reservaciones contienen al menos una
noche durante el fin de semana?

¡Excelente!, ahora que comprendes que tan importante es el uso de los filtros es probable que
requieras aplicar más de un filtro simultáneamente, para ello cuentas con los comandos AND,
OR, BETWEEN e IN.

Supongamos que queremos conocer las reservas que se han hecho en Resort Hotels y que no
han reservado noches en fines de semana (stays_in_weekend_nights cero).
⚠️ Es muy importante saber diferenciar entre AND y OR. El primero lo ocupamos cuando
queremos que ambas condiciones se cumplan, por ejemplo si quisiéramos las reservas de los
huéspedes que son españoles Y que reservaron con más de 10 días de anticipación,
correríamos una consulta con AND:

SELECT *
FROM `proyecto.dataset.tabla`
WHERE country = 'ESP' AND lead_time > 10

En cambio, si quisiéramos contar las reservas que se hicieron en 2015 O en 2017,


escribiríamos algo como:

SELECT COUNT(*)
FROM `proyecto.dataset.tabla`
WHERE arrival_date_year = 2015 OR arrival_date_year = 2017

👩‍💻 ¡Ahora es tu turno!, ¿podrías indicarnos cuantas reservaciones se realizaron en el mes


de Diciembre del año 2016?

3860

Progresivamente observarás el abanico de comandos que estáis aprendiendo, estos te


beneficiarán para poder armar un reporte correcto y en menor tiempo, no olvides que los filtros
que realices no siempre necesitarás hacerlo por alguna búsqueda exacta, en algunos casos
tendrás la necesidad de hacerlo por palabras claves (keywords), sobre todo en variables que
son de tipo texto.

Consideremos la variable “customer_type”. Esta tiene 4 posibles valores: “Transient”, “Transient-


Party”, “Contract” y “Group". Si nos piden filtrar por aquellas que son “Transient” y “Transient-
Party” podemos apoyarnos del comando LIKE.
SELECT *
FROM `proyecto.dataset.tabla`
WHERE customer_type LIKE 'Transient%'

De esa forma nos retornará solo los valores que comiencen con "Transient". El operador % nos
indica "después de esto puede venir cualquier cadena de carácteres".

👩‍💻 ¡Ahora es tu turno!, ¿podrías indicarnos cuales reservaciones canceladas


(is_canceled=1) pertenecen al “market segment” TA?

29049

Ahora que manejamos completamente los filtros exacto y aproximados, tenemos que tener en
cuenta que, dependiendo de la estructura de la tabla, en algunos casos necesitaremos crear
nuevas variables a partir de otras. Por ejemplo, este dataset tiene la fecha de llegada de la
reserva dividida en 3 variables distintas que son “arrival_date_year”, “arrival_date_month” y
“arrival_date_day_of_month”. Para poder operar sobre esta fecha es necesario unir estos
campos. Si deseamos realizar esto es necesario usar el comando CONCAT.

Vamos a crear una nueva variable (columna) que almacene la fecha completa. Le llamaremos
arrival_date. Esta nueva columna debe estar en función de las 3 variables (arrival_date_year,
arrival_date_month, arrival_date_day_of_month):

SELECT CONCAT(arrival_date_year,'-', arrival_date_month, '-',


arrival_date_day_of_month) AS arrival_date
FROM `proyecto.dataset.tabla`

¡Bien hecho! Sin embargo esta consulta no almacena la nueva variable que hemos creado,
solamente la muestra. Para agregar esta nueva variable al dataset vamos a tener que crear una
nueva tabla y agregar esta variable al final de todo el resto:

CREATE TABLE `proyecto.dataset.tabla2`


AS
SELECT *, CONCAT(arrival_date_year,'-', arrival_date_month, '-',
arrival_date_day_of_month) as arrival_date
FROM `proyecto.dataset.tabla`

Lo que hace esta consulta es crear una nueva tabla "tabla2" en el mismo dataset, del mismo
proyecto donde estamos trabajando. Esta nueva tabla contiene todas las columnas de la tabla
anterior (por eso comenzamos con el * ) y luego le agrega nuestra nueva variable arrival_date
que generamos en el paso anterior. Si todo salió bien, deberías tener una nueva tabla (con el
nombre que elegiste) en la barra de la izquierda. En mi caso esta tabla se llama "bookings2".

Y al mirar los datos en la vista previa podemos observar que esta nueva tabla contiene todas las
columnas de la tabla anterior y una nueva columna arrival_date al final

¡Genial!, has creado variables que te serán útiles más adelante, ahora el siguiente paso es
aprender a agrupar datos y crear una variable a partir de esta agrupación.

En el sector turístico muchas veces las estaciones del año reflejan temporadas altas y
temporadas bajas. Por lo cual sería útil crear una columna adicional que indique la estación del
año. Para poder conseguir esto puedes usar el comando CASE que busca crear nuevas
columnas a partir de condiciones de columnas anteriores.
Lo que queremos lograr es que si el mes de registro es Enero, Febrero o Marzo, entonces que la
nueva columna guarde la palabra "Verano". Si es Abril, Mayo o Junio, que almacene Otoño, y
así con el resto. Podemos lograr esto con un CASE para cada mes:

SELECT *,
CASE
WHEN arrival_date_month = 'January' THEN 'Verano'
WHEN arrival_date_month = 'February' THEN 'Verano'
WHEN arrival_date_month = 'March' THEN 'Verano'
WHEN arrival_date_month = 'April' THEN 'Otoño'
WHEN arrival_date_month = 'May' THEN 'Otoño'
WHEN arrival_date_month = 'June' THEN 'Otoño'
WHEN arrival_date_month = 'July' THEN 'Invierno'
WHEN arrival_date_month = 'August' THEN 'Invierno'
WHEN arrival_date_month = 'September' THEN 'Invierno'
WHEN arrival_date_month = 'October' THEN 'Primavera'
WHEN arrival_date_month = 'November' THEN 'Primavera'
WHEN arrival_date_month = 'December' THEN 'Primavera'
END AS arrival_season
FROM `proyecto.dataset.tabla2`

Si observas el resultado deberíamos haber logrado lo que nos propusimos. Sin embargo, es una
buena práctica siempre mirar formas más eficientes y cortas de escribir tus consultas para que
utilicen menos recursos y/o sean más entendibles para alguien que deba leer tu código. Una
forma de acortar esta consulta es con el comando IN, que busca si un valor está dentro de una
lista o no.

SELECT *,
CASE
WHEN arrival_date_month IN ('January', 'February', 'March') THEN
'Verano'
WHEN arrival_date_month IN ('April', 'May', 'June') THEN 'Otoño'
WHEN arrival_date_month IN ('July', 'August', 'September') THEN
'Invierno'
ELSE 'Primavera'
END AS arrival_season
FROM `proyecto.dataset.tabla2`;
Como ves además hicimos uso de la sentencia ELSE. Al haber revisado todos los primeros 9
meses del año, solo queda 1 sola posibilidad, el mes es Octubre, Noviembre o Diciembre, por lo
que al decirle ELSE 'Primavera' estamos evitando escribir una condición innecesaria.

¡Bien hecho! Recuerda que si quieres almacenar esta nueva variable vas a tener que reescribir
tu consulta pero ahora creando una nueva (tercera) tabla que tenga esta nueva columna.

👩‍💻 ¡Ahora es tu turno!, dado que ya conoces cómo usar el comando CASE, utilízalo para
crear una nueva variable "lead_time_segment" que segmente a la columna "lead_time" en tres
segmentos: "Corto" (<30 días), "Mediano" (entre 30 y 90 días) y "Largo" (más de 90 días). Aquí
puede ser útil la sentencia BETWEEN

SELECT
*,
CASE
WHEN lead_time <30 THEN 'Corto'
WHEN lead_time BETWEEN 30
AND 90 THEN 'Mediano'
WHEN lead_time >90 THEN 'largo'
END
AS arrival_season
FROM
`infinite-aura-349002.proyecto4.proyecto4`

Para que puedas sacar ventaja de las funciones implementadas por cada tipo de dato es
necesario mapear (transformar) cada variable a su tipo de dato correcto. En este caso,
necesitamos decirle a Bigquery que la columna 'arrival_date' es de tipo DATE. Para poder
mapear la columna 'arrival_date' al tipo de dato DATE, la variable tiene que estar en el siguiente
formato 'YYYY-[M]M-[D]D':

● YYYY: Año de cuatro dígitos


● [M]M: mes de uno o dos dígitos
● [D]D: día de uno o dos dígitos

Como parte de los ejercicios de aprendizaje, te proponemos modificar la variable ‘arrival_date’


de manera de que el mes se represente de forma numérica (January -> 01 ó 1) y no con el
nombre del mes (January, February, entre otros), para poder de esta manera obtener la variable
‘arrival_date’ en un formato DATE correcto. Para realizar este ejercicio debes aplicar el comando
CASE y finalmente el uso del CONCAT.

SELECT
*,
CASE
WHEN arrival_date_month = 'January' THEN 01
WHEN arrival_date_month = 'February' THEN 02
WHEN arrival_date_month = 'March' THEN 03
WHEN arrival_date_month = 'April' THEN 04
WHEN arrival_date_month = 'May' THEN 05
WHEN arrival_date_month = 'June' THEN 06
WHEN arrival_date_month = 'July' THEN 07
WHEN arrival_date_month = 'August' THEN 08
WHEN arrival_date_month = 'September' THEN 09
WHEN arrival_date_month = 'October' THEN 10
WHEN arrival_date_month = 'November' THEN 11
WHEN arrival_date_month = 'December' THEN 12
END
AS month
FROM
`infinite-aura-349002.proyecto4.proyecto4`

GUARDA COMO NUEVA TABLA

CREATE TABLE `infinite-aura-349002.proyecto4.proyecto4C`


AS

SELECT
*,
CASE
WHEN arrival_date_month = 'January' THEN 01
WHEN arrival_date_month = 'February' THEN 02
WHEN arrival_date_month = 'March' THEN 03
WHEN arrival_date_month = 'April' THEN 04
WHEN arrival_date_month = 'May' THEN 05
WHEN arrival_date_month = 'June' THEN 06
WHEN arrival_date_month = 'July' THEN 07
WHEN arrival_date_month = 'August' THEN 08
WHEN arrival_date_month = 'September' THEN 09
WHEN arrival_date_month = 'October' THEN 10
WHEN arrival_date_month = 'November' THEN 11
WHEN arrival_date_month = 'December' THEN 12
END
AS month,
FROM
`infinite-aura-349002.proyecto4.proyecto4`
GUARDAR NUEVA TABLA

Si todo salió bien, entonces tienes una nueva tabla con la variable arrival_date en su formato
correcto (por ejemplo, 2015-07-25, y no 2015-Jul-25 como teníamos antes). Sin embargo,
probablemente BigQuery todavía está almacenando esa variable como si fuera texto. Esto lo
puedes observar en el esquema:

Para cambiar tipos de datos en el esquema utilizamos la función CAST de BigQuery:

SELECT *, CAST(arrival_date AS DATE) AS arrival_date_v2


FROM proyecto.dataset.tabla

Si creas una nueva tabla con esta variable y la comparas en el esquema podrás ver que
BigQuery lo convirtió a un tipo de datos DATE.

SELECT
*,
CAST(arrival_date AS DATE) AS arrival_date_v2
FROM
`infinite-aura-349002.proyecto4.proyecto4D`

GUARDAR NUEVA TABLA

Ahora que Bigquery sabe que se trata de una variable de tipo DATE, podemos sacarle el jugo,
por ejemplo podrías filtrar las reservaciones realizadas entre septiembre 2015 y septiembre
2016. O extraer el día de la semana de cada fecha. Revisa todas las funciones que puedes
aplicar sobre una variable DATE aquí.
👩‍💻 ¡Ahora es tu turno!, sabemos que revisaste el link sugerido, ahora es tu turno de poner en
práctica lo aprendido. Es muy importante conocer la fecha en la que la reserva fue generada.
Tenemos dos variables 'arrival_date_v2' (Fecha de llegada) y 'lead_time' (días que hay entre la
fecha en que se reserva y la fecha de llegada). Así que tendrás que crear una nueva columna
"booking_date" que tenga la fecha de reserva. Como sugerencia:

● A la fecha de llegada réstale la cantidad de días de lead_time


● BigQuery permite hacer esto con la función DATE_SUB

¡Excelente trabajo! BigQuery tiene funciones que nos permite identificar de forma rápida un
estadístico de una variable. Entre estás funciones tenemos AVG(), SUM(), COUNT(), MIN(),
MAX(). Estas funciones también son conocidas como funciones de agregación. En esta sección
del curso puedes encontrar información valiosa.

Supongamos que queremos calcular cuánto pagan en promedio los huéspedes por noche de
reserva (recuerda que la variable "adr" almacena el monto pagado por noche). La función AVG
nos realiza ese cálculo:

SELECT AVG(adr)
FROM proyecto.dataset.tabla

👩‍💻 ¡Ahora es tu turno!, muestra la fecha mínima y máxima del conjunto de datos tanto para
la variable 'arrival_date_v2', como para la variable 'booking_date'. De esta forma conoceremos
desde y hasta cuando tenemos data histórica.

SELECT
MAX(arrival_date_v2)
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
2017-08-31

SELECT
MIN(arrival_date_v2)
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
2015-07-01
Supongamos que ahora queremos saber el adr promedio para cada tipo de hotel. Como
tenemos dos tipos ("Restor Hotel" y "City Hotel") podríamos escribir dos consultas para conocer
su valor:

SELECT AVG(adr)
FROM proyecto.dataset.tabla
WHERE hotel = 'City Hotel'

SELECT AVG(adr)
FROM proyecto.dataset.tabla
WHERE hotel = 'Resort Hotel'

SELECT
AVG(adr)
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
WHERE hotel = 'City Hotel'

105.30828152182164

SELECT
AVG(adr)
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
WHERE hotel = 'Resort Hotel'

94.952929605591578

Sin embargo, ¿qué pasaría si en vez de tener dos categorías de hotel esta cadena tuviera 10?
Entonces tendríamos que escribir 10 consultas para conocer el valor promedio de adr para cada
una de esas categorías. Aquí es donde se vuelve muy útil la función GROUP BY. Como su
nombre lo indica, esta función agrupa resultados según la o las columnas que le
especifiquemos. Podemos reescribir las dos consultas anteriores en una sola:

SELECT hotel, AVG(adr) AS pago_promedio_por_noche


FROM proyecto.dataset.tabla
GROUP BY hotel
SELECT
hotel,
AVG(adr) AS pago_promedio_por_noche
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
hotel

City Hotel 105.30828152182164


Resort Hotel 94.952929605591578

La sentencia GROUP BY siempre va después del FROM y del WHERE. Además debemos
especificar la columna por la cual estamos agrupando en las columnas que estamos
seleccionando. Por eso aparece la variable "hotel" tanto en el SELECT como en el GROUP
BY.👩‍💻 ¡Ahora es tu turno! Practica la sentencia GROUP BY calculando:

● 1 La cantidad de reservas que hay para cada segmento de la variable


lead_time_segment que calculaste anteriormente
● 2 La cantidad de reservas que tenemos por cada tipo de hotel durante en los años 2015
y 2016 (aquí debes utilizar WHERE además de GROUP BY)
● 3 La cantidad de reservas que existe por cada año y por cada tipo de hotel. Sugerencia:
Puedes usar más de una columna en el GROUP BY.
● 4 La cantidad de reservas que existe por cada año-mes y por cada tipo de hotel.
Sugerencia: nuevamente agrupar por más de una variable. Además te recomendamos
utilizar ORDER BY para ordenar tus resultados.
● 5 La cantidad de reservas que existe por cada año-mes y por cada tipo de hotel, pero
muestra solo aquellos meses-años en donde se hayan realizado más de 3500 reservas.
Aquí te recomendamos conocer la función HAVING para generar condiciones sobre
agrupaciones.

1
SELECT
lead_time,
count (lead_time)
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
lead_time
order by lead_time

2
SELECT
hotel,
COUNT(hotel) AS count
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
WHERE arrival_date_year BETWEEN 2015 and 2016
GROUP BY
hotel
3
SELECT
arrival_date_year,
hotel,
COUNT(*) AS contado
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
arrival_date_year,
hotel
order by
arrival_date_year

Fila arrival_date_year hotel contado

1 2015 City Hotel 13678

2 2015 Resort Hotel 8314

3 2016 City Hotel 38140

4 2016 Resort Hotel 18567

5 2017 City Hotel 27508

SELECT
month AS Mes,
arrival_date_year AS Year,
hotel,
COUNT(*) AS contado
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
month,
arrival_date_year,
hotel
ORDER BY
Hotel,
Year,
Mes
Fila Mes Year hotel contado

1 7 2015 City Hotel 1398

2 8 2015 City Hotel 2476

3 9 2015 City Hotel 3529

4 10 2015 City Hotel 3386

5 11 2015 City Hotel 1235

6 12 2015 City Hotel 1654

7 1 2016 City Hotel 1364

8 2 2016 City Hotel 2371

9 3 2016 City Hotel 3046

10 4 2016 City Hotel 3561

11 5 2016 City Hotel 3676

12 6 2016 City Hotel 3923

13 7 2016 City Hotel 3131

14 8 2016 City Hotel 3378

15 9 2016 City Hotel 3871

16 10 2016 City Hotel 4219

17 11 2016 City Hotel 3122

18 12 2016 City Hotel 2478

19 1 2017 City Hotel 2372

20 2 2017 City Hotel 2594

Se usa month por que si usamos arrival_date_month el primero seria August December, etc

5
SELECT
arrival_date_month AS Mes,
arrival_date_year AS Year,
hotel,
COUNT(*) AS contado
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
arrival_date_month,
arrival_date_year,
hotel
HAVING
contado > 3500
ORDER BY
Hotel,
Year,
Mes

ila Mes Year hotel contado

1 September 2015 City Hotel 3529

2 April 2016 City Hotel 3561

3 June 2016 City Hotel 3923

4 May 2016 City Hotel 3676

5 October 2016 City Hotel 4219

6 September 2016 City Hotel 3871

7 April 2017 City Hotel 3919

8 July 2017 City Hotel 3559

9 June 2017 City Hotel 3971

10 May 2017 City Hotel 4556

Antes de pasar a visualizar nuestros datos intentemos utilizar funciones de agrupación una
última vez para buscar la cantidad de reservas que se han hecho por tipo de hotel y por fecha:
SELECT
month AS Mes,
arrival_date_year AS Year,
hotel,
arrival_date_v2,
COUNT(*) AS Total
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
month,
arrival_date_year,
hotel,
arrival_date_v2
ORDER BY
Hotel,
Year,
Mes

Fila Mes Year hotel arrival_date_v2 Total

1 7 2015 City Hotel 2015-07-02 49

2 7 2015 City Hotel 2015-07-03 16

3 7 2015 City Hotel 2015-07-04 38

4 7 2015 City Hotel 2015-07-06 30

5 7 2015 City Hotel 2015-07-08 40

6 7 2015 City Hotel 2015-07-09 46

7 7 2015 City Hotel 2015-07-10 9


8 7 2015 City Hotel 2015-07-11 62

9 7 2015 City Hotel 2015-07-13 33

10 7 2015 City Hotel 2015-07-15 42

🆘 Si estás teniendo problema con esta consulta recuerda que puedes agrupar (GROUP BY)
por más de una columna y que además puedes aplicar funciones de agregación como
COUNT()

¿Lo lograste? ¡Espero que sí! Vamos a ir un paso más allá. Dado que queremos analizar las
cancelaciones que se han hecho en la cadena hotelera, sería interesante comparar la cantidad
de reservas (que ya calculaste en la consulta anterior) con la cantidad de cancelaciones en la
misma fecha. Intenta agregar una columna más que sume (SUM) todas las cancelaciones de la
fecha para cada tipo de hotel:

👀 Recuerda renombrar las columnas que vayas generando con algún nombre distintivo
utilizando la sentencia AS

SELECT
month AS Mes,
arrival_date_year AS Year,
hotel,
arrival_date_v2,
COUNT(*) AS Bookings,
SUM (is_canceled) AS num_canceled
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
month,
arrival_date_year,
hotel,
arrival_date_v2
ORDER BY
Hotel,
Year,
Mes

Fila Mes Year hotel arrival_date_v2 Bookings num_canceled

1 7 2015 City Hotel 2015-07-02 49 48

2 7 2015 City Hotel 2015-07-03 16 6

3 7 2015 City Hotel 2015-07-04 38 29

4 7 2015 City Hotel 2015-07-06 30 29

5 7 2015 City Hotel 2015-07-08 40 16

6 7 2015 City Hotel 2015-07-09 46 45

7 7 2015 City Hotel 2015-07-10 9 7

8 7 2015 City Hotel 2015-07-11 62 31

9 7 2015 City Hotel 2015-07-13 33 32

10 7 2015 City Hotel 2015-07-15 42 18

Guarda esta consulta ya que la utilizarás más adelante.

¡Muy bien! Has explorado los datos utilizando SQL y, en el camino, aprendiendo las funciones
más importantes del lenguaje. Sigue practicando y buscando nuevas variables/agrupaciones
que puedan ser interesantes.

CREATE TABLE
`infinite-aura-349002.proyecto4.proyecto4F` AS
SELECT
month AS Mes,
arrival_date_year AS Year,
hotel,
arrival_date_v2,
COUNT(*) AS Bookings,
SUM (is_canceled) AS num_canceled
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
month,
arrival_date_year,
hotel,
arrival_date_v2
ORDER BY
Hotel,
Year,
Mes

3. Diagnosticar las cancelaciones utilizando


visualizaciones
Ahora que sabes cómo consultar la base de datos BigQuery es momento de sacarle provecho
usando una herramienta de visualización llamada PowerBI. PowerBI te permitirá explorar los
datos con mayor facilidad. A continuación te guiaremos para poder realizar tu primera
visualización.

El primer paso será descargar la herramienta de PowerBI, lo puedes hacer desde el siguiente
enlace (descarga). Una vez descargado, deberás instalarlo y al momento de ejecutar verás una
pantalla como la siguiente:
Para visualizar nuestros datos de BigQuery en Power BI debemos crear una conexión entre
ambos. En "Obtener datos" buscamos BigQuery:
Luego haz click en la opción de Google Bigquery
Despliega la opción de “Opciones Avanzadas”, en este caso llenarás los dos últimos campos Id.
del proyecto (El nombre del proyecto que le diste en BigQuery, en mi caso será “laboratoria-
certi-turismo”) y en el segundo campo agregarás el query con la información que quieres traer a
Power BI para visualizar. Este paso lo deberás repetir tantas veces como queries quieras traer a
Power BI. Para nuestra primera visualización utilizaremos la última consulta que hicimos en la
sección anterior, donde comparamos la cantidad de reservas y la cantidad de cancelaciones por
fecha y por tipo de hotel.
👀 Si Power BI te pide conectarte con Google entonces deberás ingresar tu correo y clave
gmail con la que has estado trabajando en el ambiente de prueba de BigQuery para completar
la conexión.

Al darle a "Aceptar" te aparecerá una vista previa de los datos que importarás, dale en “cargar”.
Luego aparecerán dos opciones, si deseas importar los datos del resultado de la consulta a
PowerBI o deseas realizar consultas frecuentes a la base de datos. Selecciona la opción de
“Importar” y dale en “Aceptar”.

En la parte derecha de PowerBI aparece una sección llamada “CAMPOS”, en ella verás que se
muestra los datos que has importado con tu consulta.

Renombremos nuestro set de datos. Dale clic derecho en “Consulta1” y selecciona “Cambiar
nombre”, ponle un nombre que represente los datos que tienes, en nuestro caso le pondremos
“booking_hotel”.

Estos datos los podremos analizar de mejor forma si logramos visualizarlos. Sigue este tutorial
de Dennis para generar tu primera visualización que debería verse como esta.
🆘 En el video Dennis utiliza "Medidas" para calcular la tasa de cancelación. Si no te quedó
completamente claro recuerda que en la sección 5 del curso de Power BI puedes aprender
más.

¿Cuál es tu opinión acerca de este nivel de cancelación? Utiliza la función drill-down para mirar
los datos por año, por mes y por día. Para tener más información podrías googlear sobre los
ratios de cancelación promedio en la industria e identificar si estos números son altos, bajos o
normales.

👩‍💻 ¡Ahora es tu turno! Ahora que sabes como conectar BigQuery con Power BI te invitamos
a hacer algunos gráficos con los datos de las consultas que hiciste en la sección anterior, y de
esa manera complementar tu exploración de los datos con visualizaciones.
4. Cuantificar el impacto monetario de una cancelación
Como pudimos ver en el brief del proyecto, una cancelación afecta monetariamente al negocio
en dos frentes:

1. Al pagar comisión a la agencia de marketing por una reserva que finalmente no se


materializa. Según el brief se paga 1,5 USD por cada reserva realizada, pero luego
cuando ese huésped cancela "perdemos" esa inversión de 1,5 USD.
2. Cuando un cliente cancela con menos de 3 días de anticipación la cadena estima que
pierde USD 120.

Vamos a cuantificar estos costos por separado y luego los mostraremos en un dashboard.

4.1 Impacto de una cancelación por pago de comisión de MKT

mostrar montos
cantidad de datos

Para cuantificar este costo nos interesa saber cuántas fueron las cancelaciones por fecha para
luego multiplicarlas por 1,5 y obtener el costo total. Para hacer un análisis más completo
intentaremos construir una tabla como esta:

Si te fijas no solo tenemos la cantidad de cancelaciones, sino que también la cantidad de no-
cancelaciones y cuánto nos cuesta cada una. Todo agrupado por fecha (para luego poder hacer
visualizaciones en el tiempo).

SELECT
arrival_date_v2 AS Mes,
COUNT(Is_canceled) AS Total_Month,
SUM(Is_canceled) AS Canceled_bookings,
COUNT(Is_canceled)-SUM(Is_canceled) AS Not_Canceled_Bookings,
SUM(Is_canceled)*1.5 AS Canceled_bookings_payments,
(COUNT(Is_canceled)-SUM(Is_canceled))*1.5 AS Not_Canceled_bookings_payments
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
GROUP BY
mes,
arrival_date_year
ORDER BY
Mes

Total_ Canceled_ Not_Canceled_ Canceled_booking Not_Canceled_


Fila Mes
Month bookings Bookings s_payments bookings_payments

1 2015-07-01 122 19 103 28.5 154.5

2 2015-07-02 93 57 36 85.5 54.0

3 2015-07-03 56 19 37 28.5 55.5

4 2015-07-04 88 43 45 64.5 67.5

5 2015-07-05 53 16 37 24.0 55.5

793

👩‍💻 Algunos tips para construir esta tabla:

● Agrupa los datos por fecha


● Cuenta las reservas canceladas (sumar todas las is_canceled = 1). Aquí te
recomendamos mirar esta sección del curso.
● Las reservas no canceladas las puedes calcular restando las canceladas del total
(COUNT(*))
● Las columnas de pagos (payments) las puedes calcular multiplicando por el valor de
comisión que cobra la empresa de marketing

4.2 Impacto de una cancelación que se realiza con menos de 3 días de anticipación

Aquí el desafío continúa. No te desanimes, cada paso que avanzas te vas volviendo más
experta en SQL. Lo primero que debemos hacer es crear una nueva tabla (que llamaremos
canceled_bookings_days_diff o cómo tu prefiera) que nos muestre la fecha en que se hizo cada
reserva cancelada y la cantidad de días que transcurrieron entre que se hizo la cancelación y la
llegada del huésped.

👩‍💻 Algunos tips para construir esta tabla:


reservation_date es la fecha en que se hizo la reserva
La diferencia entre la fecha que se hizo la cancelación (que se almacena en la columna
reservation_status_date) y la llegada del huésped lo puedes calcular con la fórmula:
DATE_DIFF(fecha_de_llegada, fecha_en_que_se_hizo_la_cancelacion, DAY)

● Recuerda que solo queremos las reservas que fueron canceladas. Procura filtrar por
is_canceled = 1
● Estamos creando una nueva tabla en el dataset por lo que comienza con tu CREATE
TABLE AS antes de tu consulta

SELECT
reservation_status_date AS Reservation_Month,
arrival_date_v2 AS Arrival_Month,
DATE_DIFF(arrival_date_v2, reservation_status_date, DAY) AS
Days_Between_Cancelation_and_arrival
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
WHERE
is_canceled = 1
ORDER BY
Reservation_Month

Fila Reservation_Month Arrival_Month Days_Between_Cancelation_and_arrival

1 2014-10-17 2015-07-02 258

2 2014-10-17 2015-07-02 258

3 2014-10-17 2015-07-02 258

4 2014-10-17 2015-07-02 258

5 2014-10-17 2015-07-02 258


44220 datos

CREAMOS NUEVA TABLA Hasta aca esta igual

Ahora con esta nueva tabla podemos contar la cantidad de reservas que fueron canceladas con
menos de 3 días de anticipación

CREATE TABLE
`infinite-aura-349002.proyecto4.proyecto4G` AS
SELECT
reservation_status_date AS Reservation_Month,
arrival_date_v2 AS Arrival_Month,
DATE_DIFF(arrival_date_v2,reservation_status_date,DAY) AS
Days_Between_Cancelation_and_arrival
FROM
`infinite-aura-349002.proyecto4.proyecto4E`
WHERE
is_canceled = 1
ORDER BY
Reservation_Month

SELECT
fecha_de_reserva,
cantidad_cancelaciones_menos_de_3_dias,
cantidad_cancelaciones_menos_de_3_dias * 120
FROM
`proyecto.dataset.canceled_bookings_days_diff`
WHERE
days_between_cancelation_and_arrival < 3
GROUP BY
fecha_de_reserva

Para llegar a una tabla similar a esta:


SELECT
Reservation_Month,
count (Days_Between_Cancelation_and_arrival) as num_cancelations_less_3_days
FROM
`infinite-aura-349002.proyecto4.proyecto4G`
WHERE
Days_Between_Cancelation_and_arrival < 3
GROUP BY
Reservation_Month

SELECT
Reservation_Month,
count (Days_Between_Cancelation_and_arrival) AS num_cancelations_less_3_days,
count (Days_Between_Cancelation_and_arrival) * 120 AS Financial_Impact
FROM
`infinite-aura-349002.proyecto4.proyecto4G`
WHERE
Days_Between_Cancelation_and_arrival < 3
GROUP BY
Reservation_Month

Fila Reservation_Month num_cancelations_less_3_days Financial_Impact

1 2015-07-01 1 120

2 2015-07-02 2 240

3 2015-07-03 2 240

4 2015-07-04 2 240

5 2015-07-06 2 240

718 datos

744 correcto

Importa los datos generados en el punto 4.1 y 4.2 datos a PowerBI y genera algunas
visualizaciones para agrupar y resumir la información. En tus gráficos podrás cuantificar el
impacto de las cancelaciones en esta cadena de hoteles y entregar recomendaciones al cliente.
5. Identificar las reservas con mayor probabilidad de
cancelación
Después de conocer el impacto financiero que tienen las cancelaciones, es hora de validar las
hipótesis que discutieron con el equipo sobre los tipos de reserva que tienen mayor probabilidad
de ser canceladas. Vamos una por una:

5.1 Hipótesis 1: Las reservas que se hacen con mayor anticipación tienen
mucho riesgo de cancelarse

Probablemente lo que guía está hipótesis es que aquellas personas que reservan con mucho
tiempo de anticipación, tienen la opción de encontrar alguna oferta diferente y la probabilidad de
que haya un evento externo que lo lleve a cancelar es mayor en un gran intervalo de tiempo.

Para encontrar patrones armemos una segmentación de rangos de lead_time (tiempo entre
reserva y llegada). Ya hicimos una mini segmentación en secciones anteriores, pero vale la
pena granularizar más los rangos para tener mayor nivel de detalle: entre 0 y 15, entre 15 y 30,
entre 30 y 60, entre 60 y 90, entre 90 y 180, entre 180 y 360, y mayores a 360.
Lo primero es generar una nueva variable (columna) con esta nueva segmentación. Ya sabemos
hacer esto (tip: usa CASE 🤓). Recuerda crear una nueva tabla con esta nueva variable.

Luego, con esta nueva tabla podemos generar una nueva consulta que nos muestre la tasa de
cancelación para cada categoría que generamos. Esto lo podemos lograr usando AVG sobre la
columna is_canceled:

SELECT
AVG(is_canceled) as tasa_de_cancelacion,
categoria_de_lead_time
FROM
`proyecto.dataset.tabla_con_categoria_de_lead`
GROUP BY
categoria_de_lead_time

Estos datos los puedes importar a Power BI para generar una visualización de tasa de
cancelación vs categoría y ver si la hipótesis es correcta.

5.2 Hipótesis 2: Las reservas que incluyen hijos tienen menor riesgo de
cancelarse

Esta hipótesis es razonable. Padres que tienen hijos quieren eliminar la mayor cantidad de
incertidumbre de sus viajes por lo que probablemente reservan con anticipación y mantienen
dichas reservas.

Para esta hipótesis seguiremos una ruta similar a la anterior. Primero crearemos una tabla con
una nueva columna que indique si la reserva contiene hijos (children o babies) o no contiene.
Recuerda que esto lo puedes hacer utilizando CASE y algunas condiciones. Luego, utilizando
esa nueva tabla, corremos una consulta similar a la hipótesis 1 calculando la tasa de
cancelación para cada categoría. Deberías obtener algo similar a esto:
A primera vista pareciera que efectivamente las reservas sin hijos tienen una mayor probabilidad
de cancelación (37% vs casi 35%). Sin embargo, la diferencia es tan pequeña que nuestro
instinto de Analista de Datos nos empuja a buscar más información. En este caso vale la pena
agregar alguna otra columna al análisis para ver si existe alguna diferencia más marcada. Por
ejemplo, ¿existirá alguna diferencia entre las reservas de resorts y city hotel en cuanto a las
cancelaciones con o sin hijos? Te invitamos a sumar esa columna en tu análisis y graficar tu
resultado en PowerBI para mostrar tu resultado.

5.3 Hipótesis 3: Los usuarios que realizaron algún cambio en su reserva tienen
menor riesgo de cancelarse

Esta hipótesis se basa en la premisa de que alguien que realiza cambios en una reserva, sin
cancelarla, la está personalizando cada vez más a la experiencia que requiere. Por lo mismo, es
menos probable que termine cancelando.

Para validar esta hipótesis podemos hacer un procedimiento similar a las hipótesis anteriores:

● Crear una nueva tabla con una segmentación según la cantidad de cambios. Puedes
hacer tres categorías: 'Sin Cambios', 'Entre 1 y 10 cambios' y '10 cambios o más'.
● Generar una consulta que agrupe la nueva segmentación y calcule la tasa de
cancelación para cada caso
● Agregar algunas otras dimensiones que enriquezcan tu análisis (por ejemplo, la variable
hotel)
● No olvides visualizar estos datos en PowerBI y extraer conclusiones

5.4 Hipótesis 4: Cuando el usuario ha realizado una solicitud especial el riesgo


de cancelación es menor

Quien propuso esta hipótesis probablemente piensa que cuando un usuario se toma el tiempo
de realizar una (o varias) solicitudes especiales de atención, entonces ese huésped está más
comprometido con la reserva ya que, al igual que la hipótesis anterior, está personalizada a su
propia experiencia.

Para validar esta hipótesis no es necesario hacer una tabla adicional con una segmentación.
Puedes utilizar directamente la columna total_of_special_requests y calcular su tasa de
cancelación. Recuerda además agregar algunas otras variables que puedan sumar a tu análisis.

5.5 Hipótesis 5: Las reservas que tienen un “adr” bajo el riesgo es menor

El adr es el average daily rate, es decir, cuánto pagó en promedio el huésped por noche. Se
calcula dividiendo el pago total del huésped en la cantidad de noches que estuvo en el hotel.
Cuando un huésped accede a un adr bajo, podemos pensar que tiene más probabilidades de
mantener la reserva ya que accedió a un precio competitivo. Por el contrario, si el adr es alto,
hay mayor tentación a mirar otras ofertas de la competencia y cambiar o cancelar la reserva.

Prueba creando segmentos de adr de 100 en 100 hasta 400 y revisa si existe algún patrón con
la tasa de cancelación para cada rango.

Todas las visualizaciones que hayas generado en esta sección, te recomendamos dejarlas en
PowerBI de forma ordenada y con tus conclusiones escritas. Ese reporte te ayudará luego para
respaldar tus conclusiones en tu presentación.

In [ ]:

También podría gustarte