MG
  • Home
  • About me

On this page

  • 1a. Entendimiento del negocio
    • Contexto
    • Hipótesis a probar
  • 1b. Descripción de datos
  • 2a. Preparación de los datos
    • 2a.1 Typecasting
    • 2a.2 Manejo de duplicados
    • 2a.3 Análisis de valores atípicos
    • 2a.4 Variables con varianza cercana a cero
    • 2a.5 Valores ausentes o faltantes
  • 4. Pruebas de hipótesis
    • 4.1 ¿Los géneros difieren en “User Rating”?
    • 4.2 ¿Los géneros difieren en número de “Reviews”?
    • 4.3 ¿Los géneros difieren en términos de “Price”?
  • 5. Recapitulación y reflexiones

Test de Hipótesis: Análisis de los 50 libros más vendidos en amazon (2009 - 2019)

Hypothesis Testing
2-Sample T-Test
Mann–Whitney U test
Welch’s T-Test
Este análisis profundiza en cómo el género literario influye en la valoración de los usuarios, el número de reseñas y el precio de los bestsellers en Amazon.
Author

Micael García

Published

October 16, 2023

1a. Entendimiento del negocio

From Kaggle: Amazon Top 50 Bestselling Books 2009 - 2019

Contexto

Dataset sobre los 50 libros más vendidos de Amazon de 2009 a 2019. Contiene 550 libros, los datos se han clasificado en ficción y no-ficción utilizando Goodreads.

Hipótesis a probar

Vamos a responder a las siguientes preguntas con validez estadística:

  • ¿Los géneros difieren en “User Rating”?
  • ¿Los géneros difieren en número de “Reviews”?
  • ¿Los géneros difieren en términos de “Price”?
Matemáticas y código: en Inglés

Aunque el texto principal está en español, los términos matemáticos y el código están en inglés.

Esta práctica sigue el estándar internacional y ayuda a familiarizarse con el lenguaje técnico más utilizado en el campo de la ciencia de datos.

1b. Descripción de datos

Para empezar, importamos las librerías que vamos a utilizar:

  • Pandas: Pandas es una biblioteca esencial en la ciencia de datos que proporciona estructuras de datos flexibles y eficientes, como DataFrames, para el análisis y manipulación de datos tabulares. Es ampliamente utilizada para limpiar, transformar y analizar datos, lo que la convierte en una herramienta fundamental para la preparación de datos en proyectos de ciencia de datos.

  • Scipy: Scipy es una biblioteca que se construye sobre NumPy y ofrece una amplia variedad de módulos y funciones especializadas para aplicaciones científicas y matemáticas. Incluye herramientas para estadísticas, optimización, álgebra lineal y procesamiento de señales, lo que la hace esencial en la investigación y el análisis de datos en ciencia de datos.

  • Fuzzywuzzy: Fuzzywuzzy es una biblioteca que se utiliza en la ciencia de datos para comparar cadenas de texto difusas o parcialmente coincidentes. Es útil en la limpieza y normalización de datos de texto, así como en la identificación de similitudes entre strings, lo que es valioso en tareas como la duplicación de registros o la coincidencia de nombres en bases de datos.

  • Plotly Express: Plotly Express es una biblioteca de visualización de datos que simplifica la creación de gráficos interactivos y visuales. Es especialmente útil en la exploración de datos y la comunicación de resultados en ciencia de datos, permitiendo a los científicos de datos crear visualizaciones informativas y atractivas con facilidad.

Code
# Import libraries
import pandas as pd
from scipy import stats
from fuzzywuzzy import fuzz

# Import plotly and customize
import plotly.io as pio
import plotly.express as px

# Set a global template, e.g. "plotly_dark"
# Customize the color scheme of the chosen template, e.g. "Set2"
pio.templates.default = "plotly"
pio.templates["plotly"].layout.colorway = px.colors.qualitative.Set2

Cargamos el dataset y describimos brevemente sus características.

df = pd.read_csv("bestsellers with categories.csv")
df.head(5)
Name Author User Rating Reviews Price Year Genre
0 10-Day Green Smoothie Cleanse JJ Smith 4.7 17350 8 2016 Non Fiction
1 11/22/63: A Novel Stephen King 4.6 2052 22 2011 Fiction
2 12 Rules for Life: An Antidote to Chaos Jordan B. Peterson 4.7 18979 15 2018 Non Fiction
3 1984 (Signet Classics) George Orwell 4.7 21424 6 2017 Fiction
4 5,000 Awesome Facts (About Everything!) (Natio... National Geographic Kids 4.8 7665 12 2019 Non Fiction
Campo Tipo de Dato Descripción Ejemplo
Name Texto Título del libro. 11/22/63: A Novel
Author Texto Autor del libro. Stephen King
User Rating Numérico entre 0 y 5 (con un decimal) Calificación promedio otorgada por usuarios. 4.6
Reviews Numérico (entero) Cantidad de reseñas del libro. 2052
Price Numérico (entero) Precio de venta del libro. 22
Year Año (número entero) Año de inclusión en la lista de más vendidos. 2011
Genre Categórico Género del libro, ficción o no ficción. Ficción

Estos son los tipos de datos que se identifican en primer momento. Como veremos más adelante, estas designaciones pueden ser problemáticas según los valores que contenga el dataset y los insights que queramos obtener.

2a. Preparación de los datos

2a.1 Typecasting

Comprobamos el tipo de datos de las columnas y los modificamos conforme nuestra descripción inicial.

df.dtypes
Name            object
Author          object
User Rating    float64
Reviews          int64
Price            int64
Year             int64
Genre           object
dtype: object
categorical_columns = ["Genre", "Name", "Author"]
df[categorical_columns] = df[categorical_columns].astype("category")
df.dtypes
Name           category
Author         category
User Rating     float64
Reviews           int64
Price             int64
Year              int64
Genre          category
dtype: object

2a.2 Manejo de duplicados

Simpler approach

¿Cuantas filas son exactamente iguales?

df.duplicated().sum()
0

Es normal no encontrar duplicados en este caso, ya que hay libros que se repiten, pero es imposible que coincidan en “Year”. No es un error en sí mismo. Sin embargo, hay un problema. Las “Reviews” deberían ser las que el libro tenía en el año en el que fue uno de los más vendidos. En lugar de eso, son las del último año. Esto podría deberse a que el autor del dataset no tuvo acceso al historial de las reseñas.

Repeated Bestsellers

df[df.duplicated("Name")]
Name Author User Rating Reviews Price Year Genre
10 A Man Called Ove: A Novel Fredrik Backman 4.6 23848 8 2017 Fiction
21 All the Light We Cannot See Anthony Doerr 4.6 36348 14 2015 Fiction
33 Becoming Michelle Obama 4.8 61133 11 2019 Non Fiction
36 Between the World and Me Ta-Nehisi Coates 4.7 10070 13 2016 Non Fiction
41 Brown Bear, Brown Bear, What Do You See? Bill Martin Jr. 4.9 14344 5 2019 Fiction
... ... ... ... ... ... ... ...
543 Wonder R. J. Palacio 4.8 21625 9 2016 Fiction
544 Wonder R. J. Palacio 4.8 21625 9 2017 Fiction
547 You Are a Badass: How to Stop Doubting Your Gr... Jen Sincero 4.7 14331 8 2017 Non Fiction
548 You Are a Badass: How to Stop Doubting Your Gr... Jen Sincero 4.7 14331 8 2018 Non Fiction
549 You Are a Badass: How to Stop Doubting Your Gr... Jen Sincero 4.7 14331 8 2019 Non Fiction

199 rows × 7 columns

Hay 199 libros que han sido bestsellers durante más de un año. Es importante tener en cuenta esto para el análisis. Vamos a utilizar únicamente la muestra más reciente de cada libro.

bestsellers = df.drop_duplicates(subset="Name", keep="last")

Checking for authors or titles with different spellings

Comprobamos si hay autores o títulos iguales pero escritos diferente.

# Function to find similar author names
def find_similar(df, column):
    authors = df[column].unique()
    duplicates = []

    for i, author1 in enumerate(authors):
        for author2 in authors[i + 1 :]:
            ratio = fuzz.ratio(author1, author2)
            if ratio > 90:  # You can adjust this threshold according to your criteria
                duplicates.append((author1, author2))

    return duplicates
# Find similar author names
duplicates = find_similar(bestsellers, "Author")

print("Author names that refer to the same author but are written differently:")
for dup in duplicates:
    print(dup)

# Find similar title names
duplicates = find_similar(bestsellers, "Name")

print("Title names that refer to the same title but are written differently:")
for dup in duplicates:
    print(dup)
Author names that refer to the same author but are written differently:
('George R. R. Martin', 'George R.R. Martin')
('J.K. Rowling', 'J. K. Rowling')
Title names that refer to the same title but are written differently:
('The 5 Love Languages: The Secret to Love That Lasts', 'The 5 Love Languages: The Secret to Love that Lasts')
('The Girl Who Played with Fire (Millennium Series)', 'The Girl Who Played with Fire (Millennium)')
# Replace the names of the Authors with the correct ones
bestsellers = bestsellers.replace("George R. R. Martin", "George R.R. Martin")
bestsellers = bestsellers.replace("J. K. Rowling", "J.K. Rowling")

# Replace the names of the Authors with the correct ones
bestsellers = bestsellers.replace(
    "The 5 Love Languages: The Secret to Love That Lasts",
    "The 5 Love Languages: The Secret to Love that Lasts",
)
bestsellers = bestsellers.replace(
    "The Girl Who Played with Fire (Millennium Series)",
    "The Girl Who Played with Fire (Millennium)",
)
bestsellers
Name Author User Rating Reviews Price Year Genre
0 10-Day Green Smoothie Cleanse JJ Smith 4.7 17350 8 2016 Non Fiction
1 11/22/63: A Novel Stephen King 4.6 2052 22 2011 Fiction
2 12 Rules for Life: An Antidote to Chaos Jordan B. Peterson 4.7 18979 15 2018 Non Fiction
3 1984 (Signet Classics) George Orwell 4.7 21424 6 2017 Fiction
4 5,000 Awesome Facts (About Everything!) (Natio... National Geographic Kids 4.8 7665 12 2019 Non Fiction
... ... ... ... ... ... ... ...
538 Winter of the World: Book Two of the Century T... Ken Follett 4.5 10760 15 2012 Fiction
539 Women Food and God: An Unexpected Path to Almo... Geneen Roth 4.2 1302 11 2010 Non Fiction
544 Wonder R. J. Palacio 4.8 21625 9 2017 Fiction
545 Wrecking Ball (Diary of a Wimpy Kid Book 14) Jeff Kinney 4.9 9413 8 2019 Fiction
549 You Are a Badass: How to Stop Doubting Your Gr... Jen Sincero 4.7 14331 8 2019 Non Fiction

351 rows × 7 columns

Ideas destacadas

  • Hemos corregido las variaciones ortográficas de los títulos y autores.
  • Hemos seleccionado las muestras más recientes de cada libro.

Con esto, se ha reducido el tamaño del dataset de 550 a 351 muestras.

2a.3 Análisis de valores atípicos

selected_columns = ["Reviews", "Price"]

for column in selected_columns:
    fig = px.box(df, x=column, title=f"Boxplot of {column}")
    fig.update_layout(title_x=0.5)
    fig.show()

Ideas destacadas

Se pueden hacer tres cosas con los outliers, siguiendo la mnemotecnia 3R: rectificar, retener o remover. En este caso, podemos estar ante valores atípicos genuinos, por tanto vamos a retenerlos por el momento.

2a.4 Variables con varianza cercana a cero

Si la variance es cero, la variable no aporta información para el análisis estadístico o el modelado, por lo tanto, puede ser eliminada.

Si la variance es casi cero, también es una variable candidata a ser eliminada, ya que aporta poca información y puede generar ruido en el análisis.

Es importante tener en cuenta que el umbral para considerar una variable como “Near Zero Variance” puede variar según el contexto y el problema específico que se esté abordando.

selected_columns = ["User Rating", "Reviews", "Price"]

# Calculate the variance of each column
variances = bestsellers[selected_columns].var()

# Define a threshold for variance
threshold = 0.1

# Identify columns with near-zero or very small variance
zero_variance_cols = variances[variances <= threshold].index

print("Columns with Zero & Near Zero Variance:")
print(zero_variance_cols)
Columns with Zero & Near Zero Variance:
Index(['User Rating'], dtype='object')

La variable “User Rating” parece estar por debajo del umbral que hemos escogido arbitrariamente. Vamos a representarla gráficamente para comprender mejor la situación.

column = "User Rating"
fig = px.violin(df, x=column, title=f"Violin plot of {column}", points="all")
fig.update_layout(title_x=0.5, xaxis=dict(range=[0, 5.5]))
fig.show()

Ideas destacadas

Al trabajar con un dataset de bestsellers, la mayoría de los “User Rating” están entre 4 y 5 estrellas, mientras que inicialmente se esperaba que las muestras estuvieran repartidas entre 0 y 5.

Es importante tener esto presente en posteriores análisis, ya que casi podría considerarse una variable categórica en lugar de continua.

2a.5 Valores ausentes o faltantes

bestsellers.isnull().sum()
Name           0
Author         0
User Rating    0
Reviews        0
Price          0
Year           0
Genre          0
dtype: int64

Ideas destacadas

  • No hay missing values

4. Pruebas de hipótesis

Vamos a responder a las siguientes preguntas con validez estadística:

  • ¿Los géneros difieren en “User Rating”?
  • ¿Los géneros difieren en número de “Reviews”?
  • ¿Los géneros difieren en términos de “Price”?

4.1 ¿Los géneros difieren en “User Rating”?

Primero hagamos una exploración visual.

fig = px.violin(
    bestsellers,
    x="User Rating",
    color="Genre",
    box=True,
    points="outliers",
)

fig.update_layout(
    title_text="User Rating violin plot by Genre",
)

fig.show()

Parece que existen diferencias. ¿Pero son estadísticamente significativas? Vamos a comprobarlo con un test de hipótesis.

1. Seleccionamos la hipótesis y el nivel de significancia

H0: El “User Rating” de los libros de ficción es igual que el de los libros de no ficción.

Ha: El “User Rating” de los libros de ficción es diferente al de los libros de no ficción.

alpha = 0.05

2. Identificamos el tipo de test

Deseamos comparar las medias de dos grupos de nuestra sample. Por lo tanto, un 2-Sample t-Test parece ser adecuado. Lo primero es verificar si se cumplen los requisitos del test.

2.1 Requisitos del test
  • Tenemos una sample representativa de la population.
  • Los datos son continuos.
  • Las muestras siguen una distribución normal o hay más de 15 observaciones.
  • Los grupos son independientes.
  • Las varianzas son iguales (o al menos similares).

Examinemos nuestra sample para ver si podemos aplicar el test.

Libro de refencia

Book: Hypothesis Testing An Intuitive Guide For Making Data Driven Decisions

Page: 48

Section: 2-Sample t-Tests

Número de observaciones para cada grupo:

bestsellers["Genre"].value_counts()
Genre
Non Fiction    191
Fiction        160
Name: count, dtype: int64

Realizamos un test de normalidad para cada grupo:

fiction_bestsellers = bestsellers[bestsellers["Genre"] == "Fiction"]
nonfiction_bestsellers = bestsellers[bestsellers["Genre"] == "Non Fiction"]
def shapiro_test(data, alpha=0.05):
    """
    Perform the Shapiro-Wilk test to check the normality of the data.

    Parameters:
    data (array-like): The data to analyze.
    alpha (float): Significance level.

    Returns:
    str: The test result.
    """
    statistic, p_value = stats.shapiro(data)

    if p_value < alpha:
        return "We reject the null hypothesis. The data does not follow a normal distribution."
    else:
        return "We fail to reject the null hypothesis. The data can be considered normally distributed."


result_fiction = shapiro_test(fiction_bestsellers["User Rating"])
result_nonfiction = shapiro_test(nonfiction_bestsellers["User Rating"])

print("For fiction bestsellers:", result_fiction)
print("For non-fiction bestsellers:", result_nonfiction)
For fiction bestsellers: We reject the null hypothesis. The data does not follow a normal distribution.
For non-fiction bestsellers: We reject the null hypothesis. The data does not follow a normal distribution.

Estudiemos la relación entre las varianzas de cada grupo.

# Perform the Levene's Test
statistic, p_value = stats.levene(
    fiction_bestsellers["User Rating"], nonfiction_bestsellers["User Rating"]
)

# Significance level
alpha = 0.05

# Check for significance
if p_value < alpha:
    print("We reject the null hypothesis. The variances are not similar.")
else:
    print("We fail to reject the null hypothesis. The variances are similar.")
We reject the null hypothesis. The variances are not similar.

Volvamos sobre los requisitos del test:

  • ¿Tenemos una sample representativa de la population? Suponemos que sí.
  • ¿Los datos son continuos?
    • En este contexto, los “User Rating” que van de 0 a 5 con un único decimal pueden considerarse como datos continuos. Sin embargo, observando las gráficas, vemos que la mayoría de los valores se encuentran en un intervalo muy pequeño (mayores a 4.0). Esto dificulta considerarlos como continuos.
  • ¿Las muestras siguen una distribución normal o hay más de 15 observaciones?
    • No, las muestras no siguen una distribución normal. Pero hay más de 15 observaciones en cada grupo, gracias al teorema central del límite podemos renunciar al supuesto de normalidad.
  • ¿Los grupos son independientes? Sí.
  • ¿Las varianzas son iguales (o al menos similares)?
    • No.

Dada la falta de continuidad en los datos, vamos a realizar un test no paramétrico Mann-Whitney.

Para realizar el test utilizaremos scipy.stats.mannwhitneyu

Libro de refencia

Book:Hypothesis Testing An Intuitive Guide For Making Data Driven Decisions

Page: 341

Section: Analyzing Likert Scale Data

# Perform the Mann-Whitney U test
statistic, p_value = stats.mannwhitneyu(
    nonfiction_bestsellers["User Rating"], fiction_bestsellers["User Rating"]
)

# Print the results
print("p-value:", p_value)

# Check for significance
alpha = 0.05  # Significance level
if p_value < alpha:
    print(
        "We reject the null hypothesis. There are significant differences between the groups."
    )
else:
    print(
        "We fail to reject the null hypothesis. There are no significant differences between the groups."
    )
p-value: 0.019226481868505015
We reject the null hypothesis. There are significant differences between the groups.

Ideas destacadas

Podemos afirmar que hay diferencias significativas en términos de “User Rating” entre los libros de ficción y los de no ficción.

4.2 ¿Los géneros difieren en número de “Reviews”?

Primero hagamos una exploración visual.

fig = px.violin(
    bestsellers,
    x="Reviews",
    color="Genre",
    box=True,
    points="outliers",
)

fig.update_layout(
    title_text="Reviews violin plot by Genre",
)

fig.show()

Parece que existen difencias. ¿Pero son estadisticamente significativas? Vamos a comprobarlo con un test de hipótesis.

1. Seleccionamos la hipotesis y el nivel de significancia

H0: El número de ‘Reviews’ medio de los libros de ficción es igual que el de los libros de no ficción

Ha: El número de ‘Reviews’ medio de los libros de ficción es diferente que el de los libros de no ficción

alpha = 0.05

2. Identificamos el tipo de test

Deseamos comparar las medias de dos grupos de nuestra sample. Por lo tanto, un 2-Sample t-Test parece ser adecuado. Lo primero es verificar si se cumplen los requisitos del test.

2.1 Requisitos del test
  • Tenemos una sample representativa de la population.
  • Los datos son continuos.
  • Las muestras siguen una distribución normal o hay más de 15 observaciones.
  • Los grupos son independientes.
  • Las varianzas son iguales (o al menos similares).

Examinemos nuestra sample para ver si podemos aplicar el test.

Libro de refencia

Book: Hypothesis Testing An Intuitive Guide For Making Data Driven Decisions

Page: 48

Section: 2-Sample t-Tests

Número de observaciones para cada grupo:

bestsellers["Genre"].value_counts()
Genre
Non Fiction    191
Fiction        160
Name: count, dtype: int64

Realizamos un test de normalidad para cada grupo:

result_fiction = shapiro_test(fiction_bestsellers["Reviews"])
result_nonfiction = shapiro_test(nonfiction_bestsellers["Reviews"])

print("Para bestsellers de ficción:", result_fiction)
print("Para bestsellers de no ficción:", result_nonfiction)
Para bestsellers de ficción: We reject the null hypothesis. The data does not follow a normal distribution.
Para bestsellers de no ficción: We reject the null hypothesis. The data does not follow a normal distribution.

Estudiemos la relación entre las varianzas de cada grupo.

# Perform the Levene's Test
statistic, p_value = stats.levene(
    fiction_bestsellers["User Rating"], nonfiction_bestsellers["User Rating"]
)

# Significance level
alpha = 0.05

# Check for significance
if p_value < alpha:
    print("We reject the null hypothesis. The variances are not similar.")
else:
    print("We fail to reject the null hypothesis. The variances are similar.")
We reject the null hypothesis. The variances are not similar.

Volvamos sobre los requisitos del test:

  • ¿Tenemos una sample representativa de la population? Suponemos que sí.
  • ¿Los datos son continuos? Sí.
  • ¿Las muestras siguen una distribución normal o hay más de 15 observaciones?
    • No, las muestras no siguen una distribución normal. Pero hay más de 15 observaciones en cada grupo, gracias al teorema central del límite podemos renunciar al supuesto de normalidad.
  • ¿Los grupos son independientes? Sí.
  • ¿Las varianzas son iguales (o al menos similares)?
    • No, las varianzas no son similares.

Las varianzas no son similares. Vamos a realizar un test tipo Welch’s t-test.

Para realizar el test utilizaremos scipy.stats.ttest_ind. Es necesario definir el parámetro equal_varbool como False.

# Perform the Welch's t-test (equal_var=False)
statistic, p_value = stats.ttest_ind(
    nonfiction_bestsellers["Reviews"], fiction_bestsellers["Reviews"], equal_var=False
)

# Print the results
print("p-value:", p_value)

# Check for significance
alpha = 0.05  # Significance level
if p_value < alpha:
    print(
        "We reject the null hypothesis: There are significant differences between the groups."
    )
else:
    print(
        "We cannot reject the null hypothesis: There are no significant differences between the groups."
    )
p-value: 4.3970747273288255e-07
We reject the null hypothesis: There are significant differences between the groups.

Ideas destacadas

Podemos afirmar que hay diferencias significativas en términos de número de “Reviews” entre los libros de ficción y los de no ficción. Los libros del género de ficción obtienen, en media, más Reviews que los libros de no ficción.

4.3 ¿Los géneros difieren en términos de “Price”?

Primero hagamos una exploración visual.

fig = px.violin(
    bestsellers,
    x="Price",
    color="Genre",
    box=True,
    points="outliers",
)

fig.update_layout(
    title_text="Price violin plot by Genre",
)

fig.show()

En esta ocasión “Price” podría no variar en función del género. ¿Pero es estadísticamente significativo? Vamos a comprobarlo con un test de hipótesis.

1. Seleccionamos la hipotesis y el nivel de significancia

H0: El precio medio de los libros de ficción es igual que el de los libros de no ficción

Ha: El precio medio de los libros de ficción es diferente que el de los libros de no ficción

alpha = 0.05

2. Identificamos el tipo de test

Deseamos comparar las medias de dos grupos de nuestra sample. Por lo tanto, un 2-Sample t-Test parece ser adecuado. Lo primero es verificar si se cumplen los requisitos del test.

2.1 Requisitos del test
  • Tenemos una sample representativa de la population.
  • Los datos son continuos.
  • Las muestras siguen una distribución normal o hay más de 15 observaciones.
  • Los grupos son independientes.
  • Las varianzas son iguales (o al menos similares).

Examinemos nuestra sample para ver si podemos aplicar el test.

Libro de refencia

Book: Hypothesis Testing An Intuitive Guide For Making Data Driven Decisions

Page: 48

Section: 2-Sample t-Tests

Realizamos un test de normalidad para cada grupo:

result_fiction = shapiro_test(fiction_bestsellers["Price"])
result_nonfiction = shapiro_test(nonfiction_bestsellers["Price"])

print("Para bestsellers de ficción:", result_fiction)
print("Para bestsellers de no ficción:", result_nonfiction)
Para bestsellers de ficción: We reject the null hypothesis. The data does not follow a normal distribution.
Para bestsellers de no ficción: We reject the null hypothesis. The data does not follow a normal distribution.

Estudiemos la relación entre las varianzas de cada grupo.

# Perform the Levene's Test
statistic, p_value = stats.levene(
    fiction_bestsellers["Price"], nonfiction_bestsellers["Price"]
)

# Significance level
alpha = 0.05

# Check for significance
if p_value < alpha:
    print("We reject the null hypothesis. The variances are not similar.")
else:
    print("We fail to reject the null hypothesis. The variances are similar.")
We fail to reject the null hypothesis. The variances are similar.

Volvamos sobre los requisitos del test:

  • ¿Tenemos una sample representativa de la population? Suponemos que sí.
  • ¿Los datos son continuos? Sí.
  • ¿Las muestras siguen una distribución normal o hay más de 15 observaciones?
    • No, las muestras no siguen una distribución normal. Pero hay más de 15 observaciones en cada grupo, gracias al teorema central del límite podemos renunciar al supuesto de normalidad.
  • ¿Los grupos son independientes? Sí.
  • ¿Las varianzas son iguales (o al menos similares)? Sí.

Se cumplen los requisitos para realizar un 2-Sample t-Test.

Para realizar el test vamos a usar scipy.stats.ttest_ind.

# Perform the t-test
statistic, p_value = stats.ttest_ind(
    nonfiction_bestsellers["Price"], fiction_bestsellers["Price"]
)

# Print the results
print("p-value:", p_value)

# Check for significance
alpha = 0.05  # Significance level
if p_value < alpha:
    print(
        "We reject the null hypothesis: There are significant differences between the groups."
    )
else:
    print(
        "We cannot reject the null hypothesis: There are no significant differences between the groups."
    )
p-value: 0.1398175523683507
We cannot reject the null hypothesis: There are no significant differences between the groups.

Ideas destacadas

No encontramos diferencias en el precio en función del género del libro.

5. Recapitulación y reflexiones

Durante la preparación de los datos:

  • Hemos realizado una limpieza en el dataset, reduciendo el número de muestras para el estudio de 549 a 331.
  • Hemos descubierto que user rating concentra sus muestras en 10 valores en lugar de los 50 esperados.

Durante el estudio mediante test de hipótesis:

  • Hemos mostrado con significancia estadística que el género del libro influye tanto en el número de reviews como en el user rating.
  • Hemos mostrado con significancia estadística que el género del libro no influye en el precio del mismo.