{"cells":[{"metadata":{},"cell_type":"markdown","source":"![](http://sds.uanl.mx/wp-content/uploads/2019/11/logo-fcq-emblema.png)\n# UNIVERSIDAD AUTONOMA DE NUEVO LEON\n# FACULTAD DE CIENCIAS QUIMICAS\n\n> ## *Producto Integrador de Aprendisaje*\n\n### **Temas selectos de ingeniería**\n\n### Integrantes:\n* Victor Daniel Ponce Loya\n* Luis Donaldo Tejeda Villarreal"},{"metadata":{"_uuid":"bb32cc5d2722e96bb02725aaece54c5509bdacb9"},"cell_type":"markdown","source":"**Objetivo del notebook:**\n\nEn este bloc de notas, exploremos el conjunto de datos dado y hagamos algunas inferencias en el camino. También finalmente vamos a construir un modelo de luz de línea de base gbm para empezar. \n\n**Objetivo de la competición:**\n\nEn esta competencia, tenemos el reto de analizar un conjunto de datos de cliente de Google Merchandise Store (también conocido como GStore, donde se vende el swag de Google) para predecir los ingresos por cliente. "},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import os\nimport json\nimport numpy as np\nimport pandas as pd\nfrom pandas.io.json import json_normalize\nimport matplotlib.pyplot as plt\nimport seaborn as sns\ncolor = sns.color_palette()\n\n%matplotlib inline\n\nfrom plotly import tools\nimport plotly.offline as py\npy.init_notebook_mode(connected=True)\nimport plotly.graph_objs as go\n\n\nfrom sklearn import model_selection, preprocessing, metrics\nimport lightgbm as lgb\n\npd.options.mode.chained_assignment = None\npd.options.display.max_columns = 999","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a6868c4286025cdb431e9f6c51e4ee714d594fca"},"cell_type":"markdown","source":"**Acerca del conjunto de datos:**\n\nAl igual que la mayoría de las otras competiciones kaggle, se nos dan dos conjuntos de datos\n* train.csv\n* test.csv\n\nCada fila del conjunto de datos es una visita a la tienda. Estamos prediciendo el registro natural de la suma de todas las transacciones por usuario. \n    \nLos campos de datos de los archivos especificados son \n* fullVisitorId- Identificador único para cada usuario de Google Merchandise Store..\n* channelGrouping - El canal a través del cual el usuario llegó a la Tienda.\n* date - La fecha en la que el usuario visitó la Tienda.\n* device - Las especificaciones del dispositivo utilizado para acceder a la Tienda.\n* geoNetwork - Esta sección contiene información sobre la geografía del usuario.\n* sessionId - Un identificador único para esta visita a la tienda.\n* socialEngagementType - Tipo de interacción, ya sea \"Socialmente comprometido\" o \"No socialmente comprometido\".\n* totals - Esta sección contiene valores agregados en toda la sesión.\n* trafficSource - Esta sección contiene información sobre la fuente de tráfico desde la que se originó la sesión.\n* visitId - Identificador de esta sesión. Esto es parte del valor que normalmente se almacena como la cookie _utmb. Esto sólo es único para el usuario. Para un identificador completamente único, debe usar una combinación de fullVisitorId y visitId.\n* visitNumber - El número de sesión para este usuario. Si esta es la primera sesión, después esto se fija a 1.\n* visitStartTime - La marca de tiempo (expresada como tiempo POSIX).\n\n"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"def load_df(csv_path='../input/ga-customer-revenue-prediction/train.csv', nrows=None):\n    JSON_COLUMNS = ['device', 'geoNetwork', 'totals', 'trafficSource']\n    \n    df = pd.read_csv(csv_path, \n                     converters={column: json.loads for column in JSON_COLUMNS}, \n                     dtype={'fullVisitorId': 'str'}, # Important!!\n                     nrows=nrows)\n    \n    for column in JSON_COLUMNS:\n        column_as_df = json_normalize(df[column])\n        column_as_df.columns = [f\"{column}.{subcolumn}\" for subcolumn in column_as_df.columns]\n        df = df.drop(column, axis=1).merge(column_as_df, right_index=True, left_index=True)\n    print(f\"Loaded {os.path.basename(csv_path)}. Shape: {df.shape}\")\n    return df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e08fe7f8ec7419ba476cd52664140ed6ae736a8c"},"cell_type":"code","source":"%%time\ntrain_df = load_df()\ntest_df = load_df(\"../input/ga-customer-revenue-prediction/test.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"302c2b9449b6173ed44ad1d27d3547573368afd4"},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dcaa5e0839118e5e2d9192f450569309e8c3798d"},"cell_type":"markdown","source":"**Exploración variable de destino:**\n\nPuesto que estamos prediciendo el registro natural de suma de todas las transacciones del usuario, vamos a resumir los ingresos de la transacción a nivel de usuario y tomar un registro y luego hacer una gráfica de dispersión."},{"metadata":{"trusted":true,"_uuid":"09744db3d19167bcb29c298ee5b248004bdb01c1"},"cell_type":"code","source":"print(\"Exploración de la variable objetivo\")\n\ntrain_df[\"totals.transactionRevenue\"] = train_df[\"totals.transactionRevenue\"].astype('float')\ngdf = train_df.groupby(\"fullVisitorId\")[\"totals.transactionRevenue\"].sum().reset_index()\n\nplt.figure(figsize=(8,6))\nplt.scatter(range(gdf.shape[0]), np.sort(np.log1p(gdf[\"totals.transactionRevenue\"].values)))\nplt.xlabel('index', fontsize=12)\nplt.ylabel('Ingresos_por_transacciones', fontsize=12)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"45d9283ef187997aaf8e16acf8dbe47b7fc0a046"},"cell_type":"markdown","source":"Wow, Esto confirma las dos primeras líneas de la visión general de la competencia.\n    * La regla 80/20 ha demostrado ser cierta para muchas empresas: solo un pequeño porcentaje de clientes produce la mayor parte de los ingresos. Como tal, los equipos de marketing tienen el desafío de realizar inversiones apropiadas en estrategias promocionales.\nDe hecho, en este caso, la relación es aún menor.     "},{"metadata":{"trusted":true,"_uuid":"4a86c2c2d3a8191845bd799e1124c6d94fcc04ff"},"cell_type":"code","source":"nzi = pd.notnull(train_df[\"totals.transactionRevenue\"]).sum()\nnzr = (gdf[\"totals.transactionRevenue\"]>0).sum()\nprint(\"Número de instancias en el conjunto de trenes con ingresos distintos de cero: \", nzi, \" y la relación es: \", nzi / train_df.shape[0])\nprint(\"Número de clientes únicos con ingresos distintos de cero: \", nzr, \"y la relación es: \", nzr / gdf.shape[0])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"569d56cf56f6134872a47e89c8654aff2ca7562c"},"cell_type":"markdown","source":"Así que la proporción de ingresos que generan clientes a clientes sin ingresos está en la relación os 1.3%\n\nDado que la mayoría de las filas tienen ingresos distintos de cero, en las siguientes gráficas vamos a echar un vistazo al recuento de cada categoría de la variable junto con el número de instancias donde los ingresos no son cero.\n\n** Número de visitantes y visitantes comunes:**\n\nAhora veamos el número de visitantes únicos en el tren y el conjunto de pruebas y también el número de visitantes comunes."},{"metadata":{"trusted":true,"_uuid":"dcc528a15dda0f853516375bd7e2e73aec09ac75"},"cell_type":"code","source":"print(\"Número de visitantes únicos en el conjunto de trenes : \",train_df.fullVisitorId.nunique(), \" fuera de las filas : \",train_df.shape[0])\nprint(\"Número de visitantes únicos en el conjunto de pruebas: \",test_df.fullVisitorId.nunique(), \" fuera de las filas : \",test_df.shape[0])\nprint(\"Número de visitantes comunes en el tren y conjunto de pruebas : \",len(set(train_df.fullVisitorId.unique()).intersection(set(test_df.fullVisitorId.unique())) ))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"961119f995a317c8b937571890cf30ac66bd1969"},"cell_type":"markdown","source":"**Columnas con valores constantes: **\n\nParece que hay bastantes características con valor constante en el conjunto de trenes. Vamos a obtener la lista de estas características. Como señala Svitlana en los comentarios a continuación, no incluyamos las columnas que tienen valor constante y algunos valores nulos. "},{"metadata":{"trusted":true,"_uuid":"5eed694270d93fd7c2bc0a16a620fd329d59c2c1"},"cell_type":"code","source":"const_cols = [c for c in train_df.columns if train_df[c].nunique(dropna=False)==1 ]\nconst_cols","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"66245f8c2294398511b88d68538578a962cbdf07"},"cell_type":"markdown","source":"Son bastantes. Dado que los valores son constantes, podemos simplemente eliminarlos de nuestra lista de características y ahorrar algo de memoria y tiempo en nuestro proceso de modelado. \n\n**Información del dispositivo:**"},{"metadata":{"trusted":true,"_uuid":"c57e7e05554e2e19a694a934ffcef530baef47f4","_kg_hide-input":false},"cell_type":"code","source":"def horizontal_bar_chart(cnt_srs, color):\n    trace = go.Bar(\n        y=cnt_srs.index[::-1],\n        x=cnt_srs.values[::-1],\n        showlegend=False,\n        orientation = 'h',\n        marker=dict(\n            color=color,\n        ),\n    )\n    return trace\n\n# Device Browser\ncnt_srs = train_df.groupby('device.browser')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace1 = horizontal_bar_chart(cnt_srs[\"count\"].head(10), 'rgba(50, 171, 96, 0.6)')\ntrace2 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(10), 'rgba(50, 171, 96, 0.6)')\ntrace3 = horizontal_bar_chart(cnt_srs[\"mean\"].head(10), 'rgba(50, 171, 96, 0.6)')\n\n# Device Category\ncnt_srs = train_df.groupby('device.deviceCategory')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace4 = horizontal_bar_chart(cnt_srs[\"count\"].head(10), 'rgba(71, 58, 131, 0.8)')\ntrace5 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(10), 'rgba(71, 58, 131, 0.8)')\ntrace6 = horizontal_bar_chart(cnt_srs[\"mean\"].head(10), 'rgba(71, 58, 131, 0.8)')\n\n# Operating system\ncnt_srs = train_df.groupby('device.operatingSystem')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace7 = horizontal_bar_chart(cnt_srs[\"count\"].head(10), 'rgba(246, 78, 139, 0.6)')\ntrace8 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(10),'rgba(246, 78, 139, 0.6)')\ntrace9 = horizontal_bar_chart(cnt_srs[\"mean\"].head(10),'rgba(246, 78, 139, 0.6)')\n\n# Creating two subplots\nfig = tools.make_subplots(rows=3, cols=3, vertical_spacing=0.04, \n                          subplot_titles=[\"Navegador de dispositivos - Recuento\", \"Navegador de dispositivos - Recuento de ingresos distintos de cero\", \"Navegador de dispositivos - Ingresos medios\",\n                                          \"Categoría del dispositivo - Recuento\",  \"Categoría de dispositivo - Recuento de ingresos distintos de cero\", \"Categoría del dispositivo - Ingresos medios\", \n                                          \"Sistema operativo del dispositivo - Recuento\", \"Sistema operativo para dispositivos : recuento de ingresos distintos de cero\", \"Sistema operativo del dispositivo - Ingresos medios\"])\n\nfig.append_trace(trace1, 1, 1)\nfig.append_trace(trace2, 1, 2)\nfig.append_trace(trace3, 1, 3)\nfig.append_trace(trace4, 2, 1)\nfig.append_trace(trace5, 2, 2)\nfig.append_trace(trace6, 2, 3)\nfig.append_trace(trace7, 3, 1)\nfig.append_trace(trace8, 3, 2)\nfig.append_trace(trace9, 3, 3)\n\nfig['layout'].update(height=1200, width=1200, paper_bgcolor='rgb(233,233,233)', title=\"Gráficas de dispositivos\")\npy.iplot(fig, filename='device-plots')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"832da86bcdc9fd153d4142f4bd5430c37915e271"},"cell_type":"markdown","source":"Inferencias:\n* La distribución del navegador de dispositivos es similar tanto en el recuento como en el recuento de parcelas de ingresos distintos de cero\n* En la categoría de dispositivo frontal, el escritorio parece tener un mayor porcentaje de recuentos de ingresos distintos de cero en comparación con los dispositivos móviles.\n* En el sistema operativo del dispositivo, aunque el número de recuentos es más de Windows, el número de recuentos donde los ingresos no son cero es más para Macintosh.\n* Chrome OS también tiene un mayor porcentaje de recuentos de ingresos distintos de cero\n* En el lado del sistema operativo móvil, iOS tiene más porcentaje de recuentos de ingresos distintos de cero en comparación con Android \n\n**Exploración de fecha:**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"59eb3e903949d8345fd8747aac85eab66c0f42cd"},"cell_type":"code","source":"import datetime\n\ndef scatter_plot(cnt_srs, color):\n    trace = go.Scatter(\n        x=cnt_srs.index[::-1],\n        y=cnt_srs.values[::-1],\n        showlegend=False,\n        marker=dict(\n            color=color,\n        ),\n    )\n    return trace\n\ntrain_df['date'] = train_df['date'].apply(lambda x: datetime.date(int(str(x)[:4]), int(str(x)[4:6]), int(str(x)[6:])))\ncnt_srs = train_df.groupby('date')['totals.transactionRevenue'].agg(['size', 'count'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\"]\ncnt_srs = cnt_srs.sort_index()\n#cnt_srs.index = cnt_srs.index.astype('str')\ntrace1 = scatter_plot(cnt_srs[\"count\"], 'red')\ntrace2 = scatter_plot(cnt_srs[\"count of non-zero revenue\"], 'blue')\n\nfig = tools.make_subplots(rows=2, cols=1, vertical_spacing=0.08,\n                          subplot_titles=[\"Fecha - Recuento\", \"Fecha - Número de ingresos no nulos\"])\nfig.append_trace(trace1, 1, 1)\nfig.append_trace(trace2, 2, 1)\nfig['layout'].update(height=800, width=800, paper_bgcolor='rgb(233,233,233)', title=\"Gráficas de fecha\")\npy.iplot(fig, filename='date-plots')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3f35771ef1b28f298d1a266d24e8d2a77626ccf0"},"cell_type":"markdown","source":"Inferencias:\n* Tenemos datos del 1 de agosto de 2016 al 31 de julio de 2017 en nuestro conjunto de datos de formación\n* En noviembre de 2016, aunque hay un aumento en el número de visitantes, no hay aumento en el número de ingresos distintos de cero durante ese período de tiempo (en relación con la media)."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"08f4a090a5928029e4b47b660afd71d952002146"},"cell_type":"code","source":"test_df['date'] = test_df['date'].apply(lambda x: datetime.date(int(str(x)[:4]), int(str(x)[4:6]), int(str(x)[6:])))\ncnt_srs = test_df.groupby('date')['fullVisitorId'].size()\n\n\ntrace = scatter_plot(cnt_srs, 'red')\n\nlayout = go.Layout(\n    height=400,\n    width=800,\n    paper_bgcolor='rgb(233,233,233)',\n    title='Fechas en el conjunto de pruebas'\n)\n\ndata = [trace]\nfig = go.Figure(data=data, layout=layout)\npy.iplot(fig, filename=\"ActivationDate\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3f98518587981622a86b31c3e3ce7ab70a2a349e"},"cell_type":"markdown","source":"En el conjunto de pruebas, tenemos fechas del 2 de agosto de 2017 al 30 de abril de 2018. Así que no hay fechas comunes entre el tren y el conjunto de pruebas. Por lo tanto, podría ser una buena idea realizar la validación basada en el tiempo para este conjunto de datos.\n\n**Información geográfica:**"},{"metadata":{"_kg_hide-input":true,"trusted":true,"scrolled":true,"_uuid":"fcb64598e3f9d0931e140f56c70d4dd5dc6f7c75"},"cell_type":"code","source":"# Continent\ncnt_srs = train_df.groupby('geoNetwork.continent')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace1 = horizontal_bar_chart(cnt_srs[\"count\"].head(10), 'rgba(58, 71, 80, 0.6)')\ntrace2 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(10), 'rgba(58, 71, 80, 0.6)')\ntrace3 = horizontal_bar_chart(cnt_srs[\"mean\"].head(10), 'rgba(58, 71, 80, 0.6)')\n\n# Sub-continent\ncnt_srs = train_df.groupby('geoNetwork.subContinent')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace4 = horizontal_bar_chart(cnt_srs[\"count\"], 'orange')\ntrace5 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"], 'orange')\ntrace6 = horizontal_bar_chart(cnt_srs[\"mean\"], 'orange')\n\n# Network domain\ncnt_srs = train_df.groupby('geoNetwork.networkDomain')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace7 = horizontal_bar_chart(cnt_srs[\"count\"].head(10), 'blue')\ntrace8 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(10), 'blue')\ntrace9 = horizontal_bar_chart(cnt_srs[\"mean\"].head(10), 'blue')\n\n# Creating two subplots\nfig = tools.make_subplots(rows=3, cols=3, vertical_spacing=0.08, horizontal_spacing=0.15, \n                          subplot_titles=[\"Continente - Recuento\", \"Continente - Recuento de ingresos no cero\", \"Continente - Ingresos medios\",\n                                          \"Subcontinente - Recuento\",  \"Subcontinente - Recuento de Ingresos No Cero\", \"Subcontinente - Ingresos medios\",\n                                          \"Dominio de red - Recuento\", \"Dominio de red - Recuento de ingresos no nulo\", \"Dominio de red - Ingresos medios\"])\n\nfig.append_trace(trace1, 1, 1)\nfig.append_trace(trace2, 1, 2)\nfig.append_trace(trace3, 1, 3)\nfig.append_trace(trace4, 2, 1)\nfig.append_trace(trace5, 2, 2)\nfig.append_trace(trace6, 2, 3)\nfig.append_trace(trace7, 3, 1)\nfig.append_trace(trace8, 3, 2)\nfig.append_trace(trace9, 3, 3)\n\nfig['layout'].update(height=1500, width=1200, paper_bgcolor='rgb(233,233,233)', title=\"Parcelas de geografía\")\npy.iplot(fig, filename='geo-plots')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"acba2fcee5fe10d5985a7daf9cc88aaa7a55f4b0"},"cell_type":"markdown","source":"Inferencias:\n* En la trama del continente, podemos ver que Estados Unidos tiene tanto un mayor número de recuentos, así como el mayor número de recuentos donde los ingresos son distintos de cero\n* Aunque Asia y Europa tienen un alto número de recuentos, el número de recuentos de ingresos distintos de cero de estos continentes es comparativamente bajo. \n* Podemos inferir los dos primeros puntos de la parcela de los subcontinentes también.\n* Si el dominio de red es \"unknown.unknown\" en lugar de \"(no establecido)\", entonces el número de recuentos con ingresos distintos de cero tiende a ser menor. \n\n**Fuente de tráfico:**\n"},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"be180a4dbb76e68b449487a6dbc214a7fac35f61","scrolled":true},"cell_type":"code","source":"# Continent\ncnt_srs = train_df.groupby('trafficSource.source')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace1 = horizontal_bar_chart(cnt_srs[\"count\"].head(10), 'green')\ntrace2 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(10), 'green')\ntrace3 = horizontal_bar_chart(cnt_srs[\"mean\"].head(10), 'green')\n\n# Sub-continent\ncnt_srs = train_df.groupby('trafficSource.medium')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace4 = horizontal_bar_chart(cnt_srs[\"count\"], 'purple')\ntrace5 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"], 'purple')\ntrace6 = horizontal_bar_chart(cnt_srs[\"mean\"], 'purple')\n\n# Creating two subplots\nfig = tools.make_subplots(rows=2, cols=3, vertical_spacing=0.08, horizontal_spacing=0.15, \n                          subplot_titles=[\"Fuente de tráfico - Recuento\", \"Fuente de tráfico - Recuento de ingresos no nulo\", \"Fuente de Tráfico - Ingresos Medios\",\n                                          \"Medio de origen de tráfico - Recuento\",  \"Medio de origen de tráfico - Recuento de ingresos no nulo\", \"Medio de origen de tráfico - Ingresos medios\"\n                                          ])\n\nfig.append_trace(trace1, 1, 1)\nfig.append_trace(trace2, 1, 2)\nfig.append_trace(trace3, 1, 3)\nfig.append_trace(trace4, 2, 1)\nfig.append_trace(trace5, 2, 2)\nfig.append_trace(trace6, 2, 3)\n\nfig['layout'].update(height=1000, width=1200, paper_bgcolor='rgb(233,233,233)', title=\"Gráficas de fuentes de tráfico\")\npy.iplot(fig, filename='traffic-source-plots')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f36fe7649aba0b26a3026dd0fb6ec8e8b9b69168"},"cell_type":"markdown","source":"Inferencias:\n* En la gráfica de origen de tráfico, aunque Youtube tiene un gran número de recuentos en el conjunto de datos, el número de recuentos de ingresos distintos de cero es muy menor. \n* Google plex tiene una alta proporción de número de ingresos distintos de cero a la cuenta total en la gráfica de origen de tráfico. \n* En el medio de origen de tráfico, \"referencia\" tiene más número de ingresos distintos de cero en comparación con el medio \"orgánico\".\n\n**Perfil del visitante:**\n\nAhora veamos las variables de perfil de visitante como el número de páginas vistas por el visitante, el número de visitas del visitante y ver cómo se ven."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"6b4042af5aa1c3b5aa79ba6d60d4af3554e510e7"},"cell_type":"code","source":"\n# Page views\ncnt_srs = train_df.groupby('totals.pageviews')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", \"mean\"]\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace1 = horizontal_bar_chart(cnt_srs[\"count\"].head(60), 'cyan')\ntrace2 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(60), 'cyan')\ntrace5 = horizontal_bar_chart(cnt_srs[\"mean\"].head(60), 'cyan')\n\n# Hits\ncnt_srs = train_df.groupby('totals.hits')['totals.transactionRevenue'].agg(['size', 'count', 'mean'])\ncnt_srs.columns = [\"count\", \"count of non-zero revenue\", 'mean']\ncnt_srs = cnt_srs.sort_values(by=\"count\", ascending=False)\ntrace3 = horizontal_bar_chart(cnt_srs[\"count\"].head(60), 'black')\ntrace4 = horizontal_bar_chart(cnt_srs[\"count of non-zero revenue\"].head(60), 'black')\ntrace6 = horizontal_bar_chart(cnt_srs[\"mean\"].head(60), 'black')\n\n# Creating two subplots\nfig = tools.make_subplots(rows=2, cols=3, vertical_spacing=0.08, horizontal_spacing=0.15, \n                          subplot_titles=[\"Total de páginas vistas - Recuento\", \"Total de páginas vistas - Recuento de ingresos distintos de cero\", \"Total de páginas vistas - Ingresos medios\",\n                                          \"Total de aciertos - Recuento\",  \"Total de aciertos - Recuento de ingresos no nulo\", \"Total de aciertos - Ingresos medios\"])\n\nfig.append_trace(trace1, 1, 1)\nfig.append_trace(trace2, 1, 2)\nfig.append_trace(trace5, 1, 3)\nfig.append_trace(trace3, 2, 1)\nfig.append_trace(trace4, 2, 2)\nfig.append_trace(trace6, 2, 3)\n\nfig['layout'].update(height=1200, width=900, paper_bgcolor='rgb(233,233,233)', title=\"Gráficas de perfil de visitantes\")\npy.iplot(fig, filename='visitor-profile-plots')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fa7d921a36f47ed34e55fc566f9781e625432db0"},"cell_type":"markdown","source":"Inferencias:\n* Ambas variables parecen muy predictivas\n* La gráfica de recuento muestra la naturaleza decreciente, es decir, tenemos un recuento total muy alto para menos número de visitas y vistas de página por transacción de visitante y el recuento general disminuye cuando aumenta el número de visitas por transacción de visitante.\n* Por otro lado, podemos ver claramente que cuando aumenta el número de visitas / páginas vistas por transacción de visitante, vemos que hay un gran número de recuentos de ingresos distintos de cero. \n\n**Modelo de línea base:**\n\nAhora vamos a crear un modelo de línea base en este conjunto de datos. Antes de empezar a crear modelos, veamos los nombres de variables que hay en el conjunto de datos train y no en el conjunto de datos de prueba. "},{"metadata":{"trusted":true,"_uuid":"d008bbab982f36a922928f1dbe079202c380df33"},"cell_type":"code","source":"print(\"Variables no en prueba, sino en tren : \", set(train_df.columns).difference(set(test_df.columns)))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b0235902dbb12f2ac27c2c0442ce6b6ab50e9e61"},"cell_type":"markdown","source":"Por lo tanto, aparte de la variable de destino, hay una variable más \"trafficSource.campaignCode\" que no está presente en el conjunto de datos de prueba. Así que tenemos que eliminar esta variable al construir modelos. También podemos soltar las variables constantes que obtuvimos antes.\n\nTambién podemos quitar el \"sessionId\" ya que es un identificador único de la visita."},{"metadata":{"trusted":true,"_uuid":"13d15eed12437ae974f3ec03af6a2b6fba75ec4c"},"cell_type":"code","source":"cols_to_drop = const_cols + ['sessionId']\n\ntrain_df = train_df.drop(cols_to_drop + [\"trafficSource.campaignCode\"], axis=1)\ntest_df = test_df.drop(cols_to_drop, axis=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0f5ae722a5beceacaf32f52a6691a57f05884be0"},"cell_type":"markdown","source":"Ahora vamos a crear divisiones de desarrollo y validación basadas en el tiempo para crear el modelo. Podemos tomar los últimos dos meses como muestra de validación."},{"metadata":{"trusted":true,"_uuid":"1b4cc2fa9b1580c9d8a7ad43b5f75657e150fba3"},"cell_type":"code","source":"# Impute 0 for missing target values\ntrain_df[\"totals.transactionRevenue\"].fillna(0, inplace=True)\ntrain_y = train_df[\"totals.transactionRevenue\"].values\ntrain_id = train_df[\"fullVisitorId\"].values\ntest_id = test_df[\"fullVisitorId\"].values\n\n\n# label encode the categorical variables and convert the numerical variables to float\ncat_cols = [\"channelGrouping\", \"device.browser\", \n            \"device.deviceCategory\", \"device.operatingSystem\", \n            \"geoNetwork.city\", \"geoNetwork.continent\", \n            \"geoNetwork.country\", \"geoNetwork.metro\",\n            \"geoNetwork.networkDomain\", \"geoNetwork.region\", \n            \"geoNetwork.subContinent\", \"trafficSource.adContent\", \n            \"trafficSource.adwordsClickInfo.adNetworkType\", \n            \"trafficSource.adwordsClickInfo.gclId\", \n            \"trafficSource.adwordsClickInfo.page\", \n            \"trafficSource.adwordsClickInfo.slot\", \"trafficSource.campaign\",\n            \"trafficSource.keyword\", \"trafficSource.medium\", \n            \"trafficSource.referralPath\", \"trafficSource.source\",\n            'trafficSource.adwordsClickInfo.isVideoAd', 'trafficSource.isTrueDirect']\nfor col in cat_cols:\n    print(col)\n    lbl = preprocessing.LabelEncoder()\n    lbl.fit(list(train_df[col].values.astype('str')) + list(test_df[col].values.astype('str')))\n    train_df[col] = lbl.transform(list(train_df[col].values.astype('str')))\n    test_df[col] = lbl.transform(list(test_df[col].values.astype('str')))\n\n\nnum_cols = [\"totals.hits\", \"totals.pageviews\", \"visitNumber\", \"visitStartTime\", 'totals.bounces',  'totals.newVisits']    \nfor col in num_cols:\n    train_df[col] = train_df[col].astype(float)\n    test_df[col] = test_df[col].astype(float)\n\n# Split the train dataset into development and valid based on time \ndev_df = train_df[train_df['date']<=datetime.date(2017,5,31)]\nval_df = train_df[train_df['date']>datetime.date(2017,5,31)]\ndev_y = np.log1p(dev_df[\"totals.transactionRevenue\"].values)\nval_y = np.log1p(val_df[\"totals.transactionRevenue\"].values)\n\ndev_X = dev_df[cat_cols + num_cols] \nval_X = val_df[cat_cols + num_cols] \ntest_X = test_df[cat_cols + num_cols] ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"3de965f248a0bf1a536d9230ef0f3cb9789b0763"},"cell_type":"code","source":"# custom function to run light gbm model\ndef run_lgb(train_X, train_y, val_X, val_y, test_X):\n    params = {\n        \"objective\" : \"regression\",\n        \"metric\" : \"rmse\", \n        \"num_leaves\" : 30,\n        \"min_child_samples\" : 100,\n        \"learning_rate\" : 0.1,\n        \"bagging_fraction\" : 0.7,\n        \"feature_fraction\" : 0.5,\n        \"bagging_frequency\" : 5,\n        \"bagging_seed\" : 2018,\n        \"verbosity\" : -1\n    }\n    \n    lgtrain = lgb.Dataset(train_X, label=train_y)\n    lgval = lgb.Dataset(val_X, label=val_y)\n    model = lgb.train(params, lgtrain, 1000, valid_sets=[lgval], early_stopping_rounds=100, verbose_eval=100)\n    \n    pred_test_y = model.predict(test_X, num_iteration=model.best_iteration)\n    pred_val_y = model.predict(val_X, num_iteration=model.best_iteration)\n    return pred_test_y, model, pred_val_y\n\n# Training the model #\npred_test, model, pred_val = run_lgb(dev_X, dev_y, val_X, val_y, test_X)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a69ff5f2cb2b33b59056acd8b3048a189a20cd5a"},"cell_type":"markdown","source":"Ahora vamos a calcular la métrica de evaluación en los datos de validación como se menciona en [este nuevo hilo de discusión](https://www.kaggle.com/c/ga-customer-revenue-prediction/discussion/66737). Así que tenemos que hacer una suma para todas las transacciones del usuario y luego hacer una transformación de registro en la parte superior. También hagamos que los valores sean inferiores a 0 a 0, ya que los ingresos de transacción solo pueden ser 0 o más. "},{"metadata":{"trusted":true,"_uuid":"360ffb4d501ac2e35b274ac15efd031495c85ec3"},"cell_type":"code","source":"from sklearn import metrics\npred_val[pred_val<0] = 0\nval_pred_df = pd.DataFrame({\"fullVisitorId\":val_df[\"fullVisitorId\"].values})\nval_pred_df[\"transactionRevenue\"] = val_df[\"totals.transactionRevenue\"].values\nval_pred_df[\"PredictedRevenue\"] = np.expm1(pred_val)\n#print(np.sqrt(metrics.mean_squared_error(np.log1p(val_pred_df[\"transactionRevenue\"].values), np.log1p(val_pred_df[\"PredictedRevenue\"].values))))\nval_pred_df = val_pred_df.groupby(\"fullVisitorId\")[\"transactionRevenue\", \"PredictedRevenue\"].sum().reset_index()\nprint(np.sqrt(metrics.mean_squared_error(np.log1p(val_pred_df[\"transactionRevenue\"].values), np.log1p(val_pred_df[\"PredictedRevenue\"].values))))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"574dae973bc73351f6325db2a596a008fc8f8338"},"cell_type":"markdown","source":"Así que estamos obteniendo una puntuación de validación de 1.70** usando este método contra la puntuación de la tabla de clasificación pública de 1.44**. Así que por favor tenga cuidado mientras trata con esto. \n\nAhora vamos a preparar el archivo de envío similar al conjunto de validación."},{"metadata":{"trusted":true,"_uuid":"5a1b1b6dd5b277d59f8a4a06752c23bb8bd7a5ea"},"cell_type":"code","source":"sub_df = pd.DataFrame({\"fullVisitorId\":test_id})\npred_test[pred_test<0] = 0\nsub_df[\"PredictedLogRevenue\"] = np.expm1(pred_test)\nsub_df = sub_df.groupby(\"fullVisitorId\")[\"PredictedLogRevenue\"].sum().reset_index()\nsub_df.columns = [\"fullVisitorId\", \"PredictedLogRevenue\"]\nsub_df[\"PredictedLogRevenue\"] = np.log1p(sub_df[\"PredictedLogRevenue\"])\nsub_df.to_csv(\"baseline_lgb.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"34da0a2ac754fb22062cd99f44f2422da7b35450"},"cell_type":"code","source":"sub_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4cbf691d8f8ce6bebe84b17f729cf7c7a0ad8c9b"},"cell_type":"markdown","source":"**Importancia de la característica:**\n\nAhora echemos un vistazo a las características importantes del modelo de luz gbm."},{"metadata":{"trusted":true,"_uuid":"7a0da4195ac3e9683c29579b7700a21eb58fdcb8"},"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12,18))\nlgb.plot_importance(model, max_num_features=50, height=0.8, ax=ax)\nax.grid(False)\nplt.title(\"LightGBM - Importancia de las funciones\", fontsize=15)\nplt.ylabel(\"Funciones\")\nplt.xlabel(\"Importancia de la característica\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e0458610aa52e885eaeaf83db91312d379424d15"},"cell_type":"markdown","source":"\"totals.pageviews\" resulta ser la característica más importante seguida de \"totals.hits\" y \"visitStartTime\". "},{"metadata":{"_uuid":"e2ed97686a372b89e874864f271765cdcbe9129b"},"cell_type":"markdown","source":"**Más por venir. ¡Estén atentos! **"}],"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":4,"nbformat_minor":4}