{"nbformat":4,"nbformat_minor":0,"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.3"},"colab":{"name":"Google Play Store App Analytics (start).ipynb","provenance":[],"toc_visible":true}},"cells":[{"cell_type":"markdown","metadata":{"dc":{"key":"4"},"run_control":{"frozen":true},"tags":["context"],"id":"-Sxae4jbdiT2"},"source":["# Introduction\n","\n","In this notebook, we will do a comprehensive analysis of the Android app market by comparing thousands of apps in the Google Play store."]},{"cell_type":"markdown","metadata":{"id":"sDT5lMxadiT3"},"source":["# About the Dataset of Google Play Store Apps & Reviews"]},{"cell_type":"markdown","metadata":{"id":"5CiydsdNdiT3"},"source":["**Data Source:**
\n","App and review data was scraped from the Google Play Store by Lavanya Gupta in 2018. Original files listed [here](\n","https://www.kaggle.com/lava18/google-play-store-apps)."]},{"cell_type":"markdown","metadata":{"id":"BBKBNy4UdiT4"},"source":["# Import Statements"]},{"cell_type":"code","metadata":{"id":"_5mfFH4_diT4","executionInfo":{"status":"ok","timestamp":1602234478794,"user_tz":-60,"elapsed":594,"user":{"displayName":"Philipp Muellauer","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjjWitgsmZ0M9Wmzf-SRYD005WcMGhejWWHMUiZnFw=s64","userId":"02749974243016517270"}}},"source":["import pandas as pd\n"],"execution_count":1,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"KegC9nPDdiT7"},"source":["# Notebook Presentation"]},{"cell_type":"code","metadata":{"id":"WPL7rhJndiT7"},"source":["# Show numeric output in decimal format e.g., 2.15\n","pd.options.display.float_format = '{:,.2f}'.format"],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Uc9LOZu9diT-"},"source":["# Read the Dataset"]},{"cell_type":"code","metadata":{"id":"zU0Zisv_diT-","executionInfo":{"status":"error","timestamp":1602234486357,"user_tz":-60,"elapsed":441,"user":{"displayName":"Philipp Muellauer","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjjWitgsmZ0M9Wmzf-SRYD005WcMGhejWWHMUiZnFw=s64","userId":"02749974243016517270"}},"outputId":"f88a917e-30a1-45a4-b17a-ab21e557913c","colab":{"base_uri":"https://localhost:8080/","height":375}},"source":["df_apps = pd.read_csv('apps.csv')"],"execution_count":2,"outputs":[{"output_type":"error","ename":"FileNotFoundError","evalue":"ignored","traceback":["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m","\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)","\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdf_apps\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'apps.csv'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m","\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pandas/io/parsers.py\u001b[0m in \u001b[0;36mread_csv\u001b[0;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision)\u001b[0m\n\u001b[1;32m 684\u001b[0m )\n\u001b[1;32m 685\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 686\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_read\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilepath_or_buffer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 687\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 688\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pandas/io/parsers.py\u001b[0m in \u001b[0;36m_read\u001b[0;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[1;32m 450\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 451\u001b[0m \u001b[0;31m# Create the parser.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 452\u001b[0;31m \u001b[0mparser\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mTextFileReader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfp_or_buf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 453\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 454\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mchunksize\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0miterator\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pandas/io/parsers.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[1;32m 934\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"has_index_names\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"has_index_names\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 935\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 936\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_make_engine\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mengine\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 937\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 938\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mclose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pandas/io/parsers.py\u001b[0m in \u001b[0;36m_make_engine\u001b[0;34m(self, engine)\u001b[0m\n\u001b[1;32m 1166\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_make_engine\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mengine\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"c\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1167\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mengine\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"c\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1168\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_engine\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mCParserWrapper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1169\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1170\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mengine\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"python\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;32m/usr/local/lib/python3.6/dist-packages/pandas/io/parsers.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, src, **kwds)\u001b[0m\n\u001b[1;32m 1996\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"usecols\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0musecols\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1997\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1998\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_reader\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparsers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTextReader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msrc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1999\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munnamed_cols\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_reader\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munnamed_cols\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2000\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;32mpandas/_libs/parsers.pyx\u001b[0m in \u001b[0;36mpandas._libs.parsers.TextReader.__cinit__\u001b[0;34m()\u001b[0m\n","\u001b[0;32mpandas/_libs/parsers.pyx\u001b[0m in \u001b[0;36mpandas._libs.parsers.TextReader._setup_parser_source\u001b[0;34m()\u001b[0m\n","\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'apps.csv'"]}]},{"cell_type":"markdown","metadata":{"id":"iKvSUwQldiUA"},"source":["# Data Cleaning"]},{"cell_type":"markdown","metadata":{"id":"MWTzYZIds5L9"},"source":["**Challenge**: How many rows and columns does `df_apps` have? What are the column names? Look at a random sample of 5 different rows with [.sample()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sample.html)."]},{"cell_type":"code","metadata":{"id":"HJI7UsPrnuRf"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"fKXFjPkmnuYA"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"MUluaHF5nueH"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Hh81sMcvdiUI"},"source":["### Drop Unused Columns\n","\n","**Challenge**: Remove the columns called `Last_Updated` and `Android_Version` from the DataFrame. We will not use these columns. "]},{"cell_type":"code","metadata":{"id":"t7EMSKAOnyzI"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"YQGe1DIKdiUM"},"source":["### Find and Remove NaN values in Ratings\n","\n","**Challenge**: How may rows have a NaN value (not-a-number) in the Ratings column? Create DataFrame called `df_apps_clean` that does not include these rows. "]},{"cell_type":"code","metadata":{"id":"grcP1IOZn1Wv"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"IbQnnPaUn1Pw"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"pD26SWlxdiUV"},"source":["### Find and Remove Duplicates\n","\n","**Challenge**: Are there any duplicates in data? Check for duplicates using the [.duplicated()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.duplicated.html) function. How many entries can you find for the \"Instagram\" app? Use [.drop_duplicates()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop_duplicates.html) to remove any duplicates from `df_apps_clean`. \n"]},{"cell_type":"code","metadata":{"id":"lE7X6KG3n5pR"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"GK2rP7wgn53-"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"Wtt09kiRn6GS"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"30yZCwtKn5xC"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"AagS_wgWn5ib"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"GJrM69CfdiUh"},"source":["# Find Highest Rated Apps\n","\n","**Challenge**: Identify which apps are the highest rated. What problem might you encounter if you rely exclusively on ratings alone to determine the quality of an app?"]},{"cell_type":"code","metadata":{"id":"rp7vFHBMn7st"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"28o1Tro4diUi"},"source":["# Find 5 Largest Apps in terms of Size (MBs)\n","\n","**Challenge**: What's the size in megabytes (MB) of the largest Android apps in the Google Play Store. Based on the data, do you think there could be limit in place or can developers make apps as large as they please? "]},{"cell_type":"code","metadata":{"id":"n5r0pJCOn9Vu"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"C3gTckh7diUk"},"source":["# Find the 5 App with Most Reviews\n","\n","**Challenge**: Which apps have the highest number of reviews? Are there any paid apps among the top 50?"]},{"cell_type":"code","metadata":{"id":"TLt98G0Sn_De"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"BFoRqpezjebe"},"source":["# Plotly Pie and Donut Charts - Visualise Categorical Data: Content Ratings"]},{"cell_type":"code","metadata":{"id":"c0IIxNGnoFKM"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"TSiV6ZkjoFVg"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"7kil2mdfoFOr"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"6ZaHYNy2oFEE"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"RoPpW37xdiUm"},"source":["# Numeric Type Conversion: Examine the Number of Installs\n","\n","**Challenge**: How many apps had over 1 billion (that's right - BILLION) installations? How many apps just had a single install? \n","\n","Check the datatype of the Installs column.\n","\n","Count the number of apps at each level of installations. \n","\n","Convert the number of installations (the Installs column) to a numeric data type. Hint: this is a 2-step process. You'll have make sure you remove non-numeric characters first. "]},{"cell_type":"code","metadata":{"id":"uTNyWsPboJLq"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"yzR49fYcoJRI"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"cFjptR-JoJOE"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"8AMmxKHgoJGT"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"7T4sfNpFdiUv"},"source":["# Find the Most Expensive Apps, Filter out the Junk, and Calculate a (ballpark) Sales Revenue Estimate\n","\n","Let's examine the Price column more closely.\n","\n","**Challenge**: Convert the price column to numeric data. Then investigate the top 20 most expensive apps in the dataset.\n","\n","Remove all apps that cost more than $250 from the `df_apps_clean` DataFrame.\n","\n","Add a column called 'Revenue_Estimate' to the DataFrame. This column should hold the price of the app times the number of installs. What are the top 10 highest grossing paid apps according to this estimate? Out of the top 10 highest grossing paid apps, how many are games?\n"]},{"cell_type":"code","metadata":{"id":"CqhX2WCJoQEp"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Rgposh-CdiU4"},"source":["### The most expensive apps sub $250"]},{"cell_type":"code","metadata":{"id":"c8_n8z8XoUML"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"VGu85CLb4OOH"},"source":["### Highest Grossing Paid Apps (ballpark estimate)"]},{"cell_type":"code","metadata":{"id":"3mDi45iIoVzE"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"dc":{"key":"18"},"run_control":{"frozen":true},"tags":["context"],"id":"lvpM2MyTdiU6"},"source":["# Plotly Bar Charts & Scatter Plots: Analysing App Categories"]},{"cell_type":"code","metadata":{"id":"3L6hK0aLoYxY"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"mg50Ts9joYz1"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"WZZizlGjoYfn"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"0tTurR7qdiU9"},"source":["### Vertical Bar Chart - Highest Competition (Number of Apps)"]},{"cell_type":"code","metadata":{"id":"SFSMH00AoaMB"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"57mowetLdiU_"},"source":["### Horizontal Bar Chart - Most Popular Categories (Highest Downloads)"]},{"cell_type":"code","metadata":{"id":"zHO7eTJmocLm"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"h7aUARLtocCy"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Uxk24qMk8vrz"},"source":["### Category Concentration - Downloads vs. Competition\n","\n","**Challenge**: \n","* First, create a DataFrame that has the number of apps in one column and the number of installs in another:\n","\n","\n","\n","* Then use the [plotly express examples from the documentation](https://plotly.com/python/line-and-scatter/) alongside the [.scatter() API reference](https://plotly.com/python-api-reference/generated/plotly.express.scatter.html)to create scatter plot that looks like this. \n","\n","\n","\n","*Hint*: Use the size, hover_name and color parameters in .scatter(). To scale the yaxis, call .update_layout() and specify that the yaxis should be on a log-scale like so: yaxis=dict(type='log') "]},{"cell_type":"code","metadata":{"id":"tVvGPDY7oe5A"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"dmXDF75WdiVC"},"source":["# Extracting Nested Data from a Column\n","\n","**Challenge**: How many different types of genres are there? Can an app belong to more than one genre? Check what happens when you use .value_counts() on a column with nested values? See if you can work around this problem by using the .split() function and the DataFrame's [.stack() method](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.stack.html). \n"]},{"cell_type":"code","metadata":{"id":"3Lo69kS6ogdm"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"F3zaKvfydiVI"},"source":["# Colour Scales in Plotly Charts - Competition in Genres"]},{"cell_type":"markdown","metadata":{"id":"Ucw6RT59diVK"},"source":["**Challenge**: Can you create this chart with the Series containing the genre data? \n","\n","\n","\n","Try experimenting with the built in colour scales in Plotly. You can find a full list [here](https://plotly.com/python/builtin-colorscales/). \n","\n","* Find a way to set the colour scale using the color_continuous_scale parameter. \n","* Find a way to make the color axis disappear by using coloraxis_showscale. "]},{"cell_type":"code","metadata":{"id":"c5xbfMgxojoA"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"BIWG_10PyIzL"},"source":["# Grouped Bar Charts: Free vs. Paid Apps per Category"]},{"cell_type":"code","metadata":{"id":"ANMs7xywolDH"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"wmRXm0TW1e_Z"},"source":["**Challenge**: Use the plotly express bar [chart examples](https://plotly.com/python/bar-charts/#bar-chart-with-sorted-or-ordered-categories) and the [.bar() API reference](https://plotly.com/python-api-reference/generated/plotly.express.bar.html#plotly.express.bar) to create this bar chart: \n","\n","\n","\n","You'll want to use the `df_free_vs_paid` DataFrame that you created above that has the total number of free and paid apps per category. \n","\n","See if you can figure out how to get the look above by changing the `categoryorder` to 'total descending' as outlined in the documentation here [here](https://plotly.com/python/categorical-axes/#automatically-sorting-categories-by-name-or-total-value). "]},{"cell_type":"code","metadata":{"id":"tqOntrS7onGt"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"nbYh2tU-VZ-i"},"source":["# Plotly Box Plots: Lost Downloads for Paid Apps\n","\n","**Challenge**: Create a box plot that shows the number of Installs for free versus paid apps. How does the median number of installations compare? Is the difference large or small?\n","\n","Use the [Box Plots Guide](https://plotly.com/python/box-plots/) and the [.box API reference](https://plotly.com/python-api-reference/generated/plotly.express.box.html) to create the following chart. \n","\n","\n"]},{"cell_type":"code","metadata":{"id":"Jip3hMZ7oqLS"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Xi2NaEBPVNrP"},"source":["# Plotly Box Plots: Revenue by App Category\n","\n","**Challenge**: See if you can generate the chart below: \n","\n","\n","\n","Looking at the hover text, how much does the median app earn in the Tools category? If developing an Android app costs $30,000 or thereabouts, does the average photography app recoup its development costs?\n","\n","Hint: I've used 'min ascending' to sort the categories. "]},{"cell_type":"code","metadata":{"id":"W1iVoT8Dos7x"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"uT32ylj4WS9B"},"source":["# How Much Can You Charge? Examine Paid App Pricing Strategies by Category\n","\n","**Challenge**: What is the median price price for a paid app? Then compare pricing by category by creating another box plot. But this time examine the prices (instead of the revenue estimates) of the paid apps. I recommend using `{categoryorder':'max descending'}` to sort the categories."]},{"cell_type":"code","metadata":{"id":"AdBr0TUhouqs"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"bJnABRw3ovwr"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"id":"zSXVSlVyQ4Kz"},"source":[""],"execution_count":null,"outputs":[]}]}