{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Motivación de la elección del problema\n\nLa construcción de un modelo de predicción basado en el historial de compra de productos (en este caso, productos de las tiendas en línea del Grupo H&M) tiene un enfoque particularmente interesante al tener como resultado recomendaciones personalizadas ya que implantar la necesidad o el deseo de un producto a un cliente, resulta sumamente conveniente y de cierta manera controlador, una idea codiciada y de gran valor para todas las empresas o personas que ofrecen sus productos con el único objetivo de maximizar las ventas. \n \nEn este mismo sentido, es de igual manera motivante el lograr adelantarse al deseo o querer de alguien, predecir el gusto del cliente y ofrecer un producto antes que el cliente mismo sepa que quiere ese producto. \n \nPor último, el proyecto contiene distintos tipos de información para analizar: datos de clientes, artículos y transacciones de clientes (datos estructurados); así como textos e imágenes (datos no estructurados), lo que lo hace también atrayente para el equipo, por la diversidad de técnicas de análisis y procesamiento que se estarán aplicando. \n\n**Descripción general del problema**\n\n\n\nGrupo H&M es una familia de marcas y negocios con 53 mercados en línea y aproximadamente 4850 tiendas. Sus tiendas en línea ofrecen a los compradores una amplia selección de productos. Pero con demasiadas opciones, es posible que los clientes no encuentren rápidamente lo que les interesa o lo que están buscando y, al final, ellos podrían no realizar una compra. Para mejorar la experiencia de compra, las recomendaciones de productos son clave. Más importante aún, ayudar a los clientes a tomar las decisiones correctas también tiene implicaciones positivas para la sostenibilidad, ya que reduce las devoluciones y, por lo tanto, minimiza las emisiones del transporte.\n \nGrupo H&M requiere desarrollar recomendaciones de productos basadas en datos de transacciones previas, así como en metadatos de clientes y productos. \n \nEl proyecto se evaluará con el estadístico Mean Average Precision @ 12 (MAP@12):\n\n\\begin{equation*}\nMAP@12=\\frac{1}{U}\\sum_{u=1}^{U}\\frac{1}{min(m,12)}\\sum_{k=1}^{min(n,12)} P(k)*rel(k)\n\\end{equation*}\n\nU = Número de clientes  \nP(k) = Precisión del corte k  \nn = Número de predicciones por cliente  \nm = Número de elementos por cliente  \nrel(k) = Función indicadora, 1 si el artículo es correcto y 0 si no  \n\n**Descripción del set de datos**\n\nArchivos:\n \n* images/ - Carpeta con imágenes (.jpg) que corresponden a cada artículo. Nota: no todos los artículos tienen una imagen.\n* articles.csv – Detalle de cada artículo disponible para compra.\n* customers.csv - Datos del cliente\n* sample_submission.csv – Ejemplo del archivo de envío (formato requerido)\n* transaction_train.csv - Datos de las compras de cada cliente.\n\n\n","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom pathlib import Path\nimport os\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:10:52.719180Z","iopub.execute_input":"2023-05-19T00:10:52.720257Z","iopub.status.idle":"2023-05-19T00:10:54.319634Z","shell.execute_reply.started":"2023-05-19T00:10:52.720210Z","shell.execute_reply":"2023-05-19T00:10:54.317971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.chdir('/kaggle/input/h-and-m-personalized-fashion-recommendations')\n","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:10:54.327046Z","iopub.execute_input":"2023-05-19T00:10:54.328476Z","iopub.status.idle":"2023-05-19T00:10:54.333478Z","shell.execute_reply.started":"2023-05-19T00:10:54.328421Z","shell.execute_reply":"2023-05-19T00:10:54.332267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preprocesamiento y limpieza de los datos","metadata":{}},{"cell_type":"code","source":"dataframes_dict = {}\nfor filename in os.listdir():\n    if filename.endswith(\".csv\"):\n        dataframes_dict[filename] = pd.read_csv(filename)\n        for key in dataframes_dict:\n            globals()[key[:-4]] = pd.DataFrame(dataframes_dict[key])\nprint(\"Las dataframes son: \")\n[key[:-4] for key in dataframes_dict]","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:10:54.344072Z","iopub.execute_input":"2023-05-19T00:10:54.344850Z","iopub.status.idle":"2023-05-19T00:12:28.269787Z","shell.execute_reply.started":"2023-05-19T00:10:54.344808Z","shell.execute_reply":"2023-05-19T00:12:28.265509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Imprimir la información de cada dataframe creado\nfor key in dataframes_dict:\n    print(\"La información de la dataframe \" + key[:-4] + \" es: \"\"\\n\")\n    print(key[:-4])\n    print(dataframes_dict[key].info())\n    print(\"\")","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:12:28.274320Z","iopub.execute_input":"2023-05-19T00:12:28.274713Z","iopub.status.idle":"2023-05-19T00:12:31.840480Z","shell.execute_reply.started":"2023-05-19T00:12:28.274677Z","shell.execute_reply":"2023-05-19T00:12:31.838883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Preprocesamiento y limpieza de los datos de Clientes","metadata":{}},{"cell_type":"code","source":"# Lectura de los archivos\n\n# Clientes\ncustomers_df = pd.read_csv('customers.csv')\ntotal_rows = customers_df.shape[0]\n\n# Transacciones\ntransactions_df = pd.read_csv('transactions_train.csv')\n#transactions_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:12:31.842016Z","iopub.execute_input":"2023-05-19T00:12:31.842518Z","iopub.status.idle":"2023-05-19T00:13:41.392628Z","shell.execute_reply.started":"2023-05-19T00:12:31.842472Z","shell.execute_reply":"2023-05-19T00:13:41.389999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Conteo de valores únicos\nprint(\"Conteo valores únicos FN: \\n\", customers_df[\"FN\"].value_counts(dropna = False))\nprint(\"\\n\")\nprint(\"Conteo valores únicos Active: \\n\", customers_df[\"Active\"].value_counts(dropna = False))\nprint(\"\\n\")\nprint(\"Conteo valores únicos Club member status: \\n\", customers_df[\"club_member_status\"].value_counts(dropna = False))\nprint(\"\\n\")\nprint(\"Conteo valores únicos Fashion news frequency: \\n\", customers_df[\"fashion_news_frequency\"].value_counts(dropna = False))\nprint(\"\\n\")\nprint(\"Conteo valores únicos Postal code: \\n\", customers_df[\"postal_code\"].value_counts(dropna = False))","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:41.396877Z","iopub.execute_input":"2023-05-19T00:13:41.397482Z","iopub.status.idle":"2023-05-19T00:13:42.808826Z","shell.execute_reply.started":"2023-05-19T00:13:41.397406Z","shell.execute_reply":"2023-05-19T00:13:42.807232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Análisis de Missing values\ndef get_missing_values(column_name):\n    missing_val = customers_df[column_name].isnull().sum()\n    percent = round((missing_val * 100)/total_rows, 2)\n    good_val = round(100 - percent, 2)\n    return percent, good_val","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:42.810599Z","iopub.execute_input":"2023-05-19T00:13:42.810997Z","iopub.status.idle":"2023-05-19T00:13:42.817130Z","shell.execute_reply.started":"2023-05-19T00:13:42.810962Z","shell.execute_reply":"2023-05-19T00:13:42.816209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Columna FN\nmissing_fn, good_fn = get_missing_values(\"FN\")\nprint(\"Missing values en FN: \" + str(missing_fn) + \"%\")\nprint(\"Valores válidos en FN: \" + str(good_fn) + \"%\")\nprint(\"\\n\")\n\n# Columna Active\nmissing_active, good_active = get_missing_values(\"Active\")\nprint(\"Missing values en Active: \" + str(missing_active) + \"%\")\nprint(\"Valores válidos en Active: \" + str(good_active) + \"%\")\nprint(\"\\n\")\n\n# Columna Club member status\nmissing_club, good_club = get_missing_values(\"club_member_status\")\nprint(\"Missing values en Club member status: \" + str(missing_club) + \"%\")\nprint(\"Valores válidos en Club member status: \" + str(good_club) + \"%\")\nprint(\"\\n\")\n\n# Columna Fashion news frequency\nmissing_news, good_news = get_missing_values(\"fashion_news_frequency\")\nprint(\"Missing values en Fashion news frequency: \" + str(missing_news) + \"%\")\nprint(\"Valores válidos en Fashion news frequency: \" + str(good_news) + \"%\")\nprint(\"\\n\")\n\n# Age\nmissing_age, good_age = get_missing_values(\"age\")\nprint(\"Missing values en Age: \" + str(missing_age) + \"%\")\nprint(\"Valores válidos en Age: \" + str(good_age) + \"%\")","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:42.821788Z","iopub.execute_input":"2023-05-19T00:13:42.822199Z","iopub.status.idle":"2023-05-19T00:13:43.137805Z","shell.execute_reply.started":"2023-05-19T00:13:42.822142Z","shell.execute_reply":"2023-05-19T00:13:43.136406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Tabla de contingencia FN y Active\npd.crosstab(index=customers_df['FN'], columns=customers_df['Active'], margins=True)","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:43.139271Z","iopub.execute_input":"2023-05-19T00:13:43.139621Z","iopub.status.idle":"2023-05-19T00:13:43.458180Z","shell.execute_reply.started":"2023-05-19T00:13:43.139592Z","shell.execute_reply":"2023-05-19T00:13:43.456855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Eliminación de columnas no requeridas para el análisis de recomendaciones\ncustomers_df = customers_df.drop(['FN', 'fashion_news_frequency', 'club_member_status'], axis=1)\ncustomers_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:43.460135Z","iopub.execute_input":"2023-05-19T00:13:43.460897Z","iopub.status.idle":"2023-05-19T00:13:43.604270Z","shell.execute_reply.started":"2023-05-19T00:13:43.460851Z","shell.execute_reply":"2023-05-19T00:13:43.603168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Se eliminan clientes sin edad\ncust_with_age_df = customers_df[customers_df['age'].notna()]","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:43.605842Z","iopub.execute_input":"2023-05-19T00:13:43.606240Z","iopub.status.idle":"2023-05-19T00:13:43.715259Z","shell.execute_reply.started":"2023-05-19T00:13:43.606206Z","shell.execute_reply":"2023-05-19T00:13:43.714230Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Análisis exploratorio de datos","metadata":{}},{"cell_type":"markdown","source":"### Análisis exploratorio de datos de Clientes","metadata":{}},{"cell_type":"code","source":"# Histogram de edad de clientes\nplt.figure(figsize=(12,6))\nplt.title(\"Customers Age\")\nsns.histplot(data=customers_df['age'])","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:43.716754Z","iopub.execute_input":"2023-05-19T00:13:43.718467Z","iopub.status.idle":"2023-05-19T00:13:46.269297Z","shell.execute_reply.started":"2023-05-19T00:13:43.718406Z","shell.execute_reply":"2023-05-19T00:13:46.268192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Análisis outliers de Edad\nsns.boxplot(customers_df['age'])\n\n# Cálculo IQR\n# IQR\nQ1 = customers_df['age'].quantile(0.25)\nQ3 = customers_df['age'].quantile(0.75)\nIQR = Q3 - Q1\n\nprint(\"Valor Q1:\", Q1)\nprint(\"Valor Q3:\", Q3)\nprint(\"Valor calculado IQR:\", IQR)\n\n# Cálculo de límites inferior y superior\nupper_limit = Q3 + 1.5 * IQR\nlower_limit = Q1 - 1.5 * IQR\n\nprint(\"Valor límite inferior:\", lower_limit)\nprint(\"Valor límite superior:\", upper_limit)","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:46.271338Z","iopub.execute_input":"2023-05-19T00:13:46.272287Z","iopub.status.idle":"2023-05-19T00:13:46.597704Z","shell.execute_reply.started":"2023-05-19T00:13:46.272218Z","shell.execute_reply":"2023-05-19T00:13:46.596109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Conteo de clientes outliers\nage_outliers_df = customers_df[customers_df['age'] > upper_limit]\nprint(\"Total de clientes outliers\", len(age_outliers_df))","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:46.599626Z","iopub.execute_input":"2023-05-19T00:13:46.600124Z","iopub.status.idle":"2023-05-19T00:13:46.613454Z","shell.execute_reply.started":"2023-05-19T00:13:46.600078Z","shell.execute_reply":"2023-05-19T00:13:46.611734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Conteo de transacciones de clientes outliers\ntrans_age_outliers = transactions_df.merge(age_outliers_df, on=['customer_id','customer_id'])\nprint(\"Total de transacciones de clientes outliers\", len(trans_age_outliers))","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:13:46.615534Z","iopub.execute_input":"2023-05-19T00:13:46.616081Z","iopub.status.idle":"2023-05-19T00:14:17.809061Z","shell.execute_reply.started":"2023-05-19T00:13:46.616034Z","shell.execute_reply":"2023-05-19T00:14:17.807664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Conteo de clientes con Nan en Edad\nage_nan = customers_df[customers_df['age'].isna()]\nprint(\"Total de clientes con Edad Nan\", len(age_nan))","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:14:17.810919Z","iopub.execute_input":"2023-05-19T00:14:17.811294Z","iopub.status.idle":"2023-05-19T00:14:17.830700Z","shell.execute_reply.started":"2023-05-19T00:14:17.811262Z","shell.execute_reply":"2023-05-19T00:14:17.828784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Conteo de transacciones de clientes con Edad Nan\ntrans_age_nan = transactions_df.merge(age_nan, on=['customer_id','customer_id'])\nprint(\"Total de transacciones de clientes con Edad Nan\", len(trans_age_nan))","metadata":{"execution":{"iopub.status.busy":"2023-05-19T00:14:17.832817Z","iopub.execute_input":"2023-05-19T00:14:17.833251Z","iopub.status.idle":"2023-05-19T00:14:49.206738Z","shell.execute_reply.started":"2023-05-19T00:14:17.833214Z","shell.execute_reply":"2023-05-19T00:14:49.205183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Selección y entrenamiento de los modelos","metadata":{}},{"cell_type":"markdown","source":"## Evaluación y comparación de los modelos","metadata":{}},{"cell_type":"markdown","source":"## Comunicación y presentación de los resultados","metadata":{}}]}