{"id":18268436,"url":"https://github.com/coreyjs/identify_customer_segments","last_synced_at":"2026-03-01T04:37:04.933Z","repository":{"id":73449923,"uuid":"314109690","full_name":"coreyjs/identify_customer_segments","owner":"coreyjs","description":"A Jupyter notebook that run PCA and KMeans on population demographic data.","archived":false,"fork":false,"pushed_at":"2020-12-23T01:52:48.000Z","size":2396,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T02:46:58.869Z","etag":null,"topics":["clustering","clustering-algorithm","identify-segments","kmeans","notebook","pca","population","udacity","udacity-nanodegree"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coreyjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-19T02:02:04.000Z","updated_at":"2020-12-23T01:52:50.000Z","dependencies_parsed_at":"2023-02-24T04:15:29.047Z","dependency_job_id":null,"html_url":"https://github.com/coreyjs/identify_customer_segments","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/coreyjs/identify_customer_segments","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreyjs%2Fidentify_customer_segments","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreyjs%2Fidentify_customer_segments/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreyjs%2Fidentify_customer_segments/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreyjs%2Fidentify_customer_segments/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coreyjs","download_url":"https://codeload.github.com/coreyjs/identify_customer_segments/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coreyjs%2Fidentify_customer_segments/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29960253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T01:47:18.291Z","status":"online","status_checked_at":"2026-03-01T02:00:07.437Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clustering","clustering-algorithm","identify-segments","kmeans","notebook","pca","population","udacity","udacity-nanodegree"],"created_at":"2024-11-05T11:31:32.106Z","updated_at":"2026-03-01T04:37:04.904Z","avatar_url":"https://github.com/coreyjs.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"### Identify Customer Segments\n\nA notebook on analysing generic population and demograhic data.  In this notebook we use PCA along side KMeans algorithm to identify segments of the population.  \nThis project is about applying these unsupervised learning techniques to identify segments that can tell us the demographic with the higest rate of return.\n\n![Screenshot 2020-11-23 202959](https://user-images.githubusercontent.com/1228838/100035062-4db12c80-2dcb-11eb-9523-3e57e3af0350.png)\n\n![Screenshot 2020-11-23 203125](https://user-images.githubusercontent.com/1228838/100035060-4db12c80-2dcb-11eb-85a2-c2653a8ed12f.png)\n\n![Screenshot 2020-11-23 203211](https://user-images.githubusercontent.com/1228838/100035061-4db12c80-2dcb-11eb-9dde-ece1900f8b09.png)\n\n\n----\n\n\n\n\n# Project: Identify Customer Segments\n\nIn this project, you will apply unsupervised learning techniques to identify segments of the population that form the core customer base for a mail-order sales company in Germany. These segments can then be used to direct marketing campaigns towards audiences that will have the highest expected rate of returns. The data that you will use has been provided by our partners at Bertelsmann Arvato Analytics, and represents a real-life data science task.\n\nThis notebook will help you complete this task by providing a framework within which you will perform your analysis steps. In each step of the project, you will see some text describing the subtask that you will perform, followed by one or more code cells for you to complete your work. **Feel free to add additional code and markdown cells as you go along so that you can explore everything in precise chunks.** The code cells provided in the base template will outline only the major tasks, and will usually not be enough to cover all of the minor tasks that comprise it.\n\nIt should be noted that while there will be precise guidelines on how you should handle certain tasks in the project, there will also be places where an exact specification is not provided. **There will be times in the project where you will need to make and justify your own decisions on how to treat the data.** These are places where there may not be only one way to handle the data. In real-life tasks, there may be many valid ways to approach an analysis task. One of the most important things you can do is clearly document your approach so that other scientists can understand the decisions you've made.\n\nAt the end of most sections, there will be a Markdown cell labeled **Discussion**. In these cells, you will report your findings for the completed section, as well as document the decisions that you made in your approach to each subtask. **Your project will be evaluated not just on the code used to complete the tasks outlined, but also your communication about your observations and conclusions at each stage.**\n\n\n```python\n# import libraries here; add more as necessary\nfrom collections import Counter\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.preprocessing import OneHotEncoder\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.impute import SimpleImputer\nfrom sklearn.decomposition import PCA\nfrom sklearn.cluster import KMeans\nfrom mpl_toolkits.mplot3d import Axes3D\n\n\n# magic word for producing visualizations in notebook\n%matplotlib inline\n\n'''\nImport note: The classroom currently uses sklearn version 0.19.\nIf you need to use an imputer, it is available in sklearn.preprocessing.Imputer,\ninstead of sklearn.impute as in newer versions of sklearn.\n'''\n```\n\n\n\n\n    '\\nImport note: The classroom currently uses sklearn version 0.19.\\nIf you need to use an imputer, it is available in sklearn.preprocessing.Imputer,\\ninstead of sklearn.impute as in newer versions of sklearn.\\n'\n\n\n\n### Step 0: Load the Data\n\nThere are four files associated with this project (not including this one):\n\n- `Udacity_AZDIAS_Subset.csv`: Demographics data for the general population of Germany; 891211 persons (rows) x 85 features (columns).\n- `Udacity_CUSTOMERS_Subset.csv`: Demographics data for customers of a mail-order company; 191652 persons (rows) x 85 features (columns).\n- `Data_Dictionary.md`: Detailed information file about the features in the provided datasets.\n- `AZDIAS_Feature_Summary.csv`: Summary of feature attributes for demographics data; 85 features (rows) x 4 columns\n\nEach row of the demographics files represents a single person, but also includes information outside of individuals, including information about their household, building, and neighborhood. You will use this information to cluster the general population into groups with similar demographic properties. Then, you will see how the people in the customers dataset fit into those created clusters. The hope here is that certain clusters are over-represented in the customers data, as compared to the general population; those over-represented clusters will be assumed to be part of the core userbase. This information can then be used for further applications, such as targeting for a marketing campaign.\n\nTo start off with, load in the demographics data for the general population into a pandas DataFrame, and do the same for the feature attributes summary. Note for all of the `.csv` data files in this project: they're semicolon (`;`) delimited, so you'll need an additional argument in your [`read_csv()`](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html) call to read in the data properly. Also, considering the size of the main dataset, it may take some time for it to load completely.\n\nOnce the dataset is loaded, it's recommended that you take a little bit of time just browsing the general structure of the dataset and feature summary file. You'll be getting deep into the innards of the cleaning in the first major step of the project, so gaining some general familiarity can help you get your bearings.\n\n\n```python\n# Load in the general demographics data.\nazdias = pd.read_csv('Udacity_AZDIAS_Subset.csv', delimiter=';')\n```\n\n\n```python\n# Load in the feature summary file.\nfeat_info = pd.read_csv('AZDIAS_Feature_Summary.csv', delimiter=';')\n```\n\n\n```python\nazdias.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eAGER_TYP\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e6.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e5 rows × 85 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\nazdias.shape\n```\n\n\n\n\n    (891221, 85)\n\n\n\n\n```python\nazdias.describe()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eAGER_TYP\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003ecount\u003c/th\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e886367.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e794005.000000\u003c/td\u003e\n      \u003ctd\u003e794005.000000\u003c/td\u003e\n      \u003ctd\u003e794005.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003emean\u003c/th\u003e\n      \u003ctd\u003e-0.358435\u003c/td\u003e\n      \u003ctd\u003e2.777398\u003c/td\u003e\n      \u003ctd\u003e1.522098\u003c/td\u003e\n      \u003ctd\u003e3.632838\u003c/td\u003e\n      \u003ctd\u003e3.074528\u003c/td\u003e\n      \u003ctd\u003e2.821039\u003c/td\u003e\n      \u003ctd\u003e3.401106\u003c/td\u003e\n      \u003ctd\u003e3.033328\u003c/td\u003e\n      \u003ctd\u003e2.874167\u003c/td\u003e\n      \u003ctd\u003e3.075121\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.253330\u003c/td\u003e\n      \u003ctd\u003e2.801858\u003c/td\u003e\n      \u003ctd\u003e1.595426\u003c/td\u003e\n      \u003ctd\u003e0.699166\u003c/td\u003e\n      \u003ctd\u003e1.943913\u003c/td\u003e\n      \u003ctd\u003e3.612821\u003c/td\u003e\n      \u003ctd\u003e3.381087\u003c/td\u003e\n      \u003ctd\u003e3.167854\u003c/td\u003e\n      \u003ctd\u003e5.293002\u003c/td\u003e\n      \u003ctd\u003e3.07222\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003estd\u003c/th\u003e\n      \u003ctd\u003e1.198724\u003c/td\u003e\n      \u003ctd\u003e1.068775\u003c/td\u003e\n      \u003ctd\u003e0.499512\u003c/td\u003e\n      \u003ctd\u003e1.595021\u003c/td\u003e\n      \u003ctd\u003e1.321055\u003c/td\u003e\n      \u003ctd\u003e1.464749\u003c/td\u003e\n      \u003ctd\u003e1.322134\u003c/td\u003e\n      \u003ctd\u003e1.529603\u003c/td\u003e\n      \u003ctd\u003e1.486731\u003c/td\u003e\n      \u003ctd\u003e1.353248\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.972008\u003c/td\u003e\n      \u003ctd\u003e0.920309\u003c/td\u003e\n      \u003ctd\u003e0.986736\u003c/td\u003e\n      \u003ctd\u003e0.727137\u003c/td\u003e\n      \u003ctd\u003e1.459654\u003c/td\u003e\n      \u003ctd\u003e0.973967\u003c/td\u003e\n      \u003ctd\u003e1.111598\u003c/td\u003e\n      \u003ctd\u003e1.002376\u003c/td\u003e\n      \u003ctd\u003e2.303739\u003c/td\u003e\n      \u003ctd\u003e1.36298\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003emin\u003c/th\u003e\n      \u003ctd\u003e-1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e1.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e25%\u003c/th\u003e\n      \u003ctd\u003e-1.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e2.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e50%\u003c/th\u003e\n      \u003ctd\u003e-1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e3.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e75%\u003c/th\u003e\n      \u003ctd\u003e-1.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e7.000000\u003c/td\u003e\n      \u003ctd\u003e4.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003emax\u003c/th\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e9.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e6.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e9.000000\u003c/td\u003e\n      \u003ctd\u003e9.000000\u003c/td\u003e\n      \u003ctd\u003e9.00000\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e8 rows × 81 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\nfeat_info.shape\n```\n\n\n\n\n    (85, 4)\n\n\n\n\n```python\nfeat_info.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eattribute\u003c/th\u003e\n      \u003cth\u003einformation_level\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003emissing_or_unknown\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003eAGER_TYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[-1,0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003eALTERSKATEGORIE_GROB\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1,0,9]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003eANREDE_KZ\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[-1,0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003eCJT_GESAMTTYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003eFINANZ_MINIMALIST\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1]\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\n\n\n\n```python\nfeat_info.describe()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eattribute\u003c/th\u003e\n      \u003cth\u003einformation_level\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003emissing_or_unknown\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003ecount\u003c/th\u003e\n      \u003ctd\u003e85\u003c/td\u003e\n      \u003ctd\u003e85\u003c/td\u003e\n      \u003ctd\u003e85\u003c/td\u003e\n      \u003ctd\u003e85\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003eunique\u003c/th\u003e\n      \u003ctd\u003e85\u003c/td\u003e\n      \u003ctd\u003e9\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e9\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003etop\u003c/th\u003e\n      \u003ctd\u003eSHOPPER_TYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003efreq\u003c/th\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e43\u003c/td\u003e\n      \u003ctd\u003e49\u003c/td\u003e\n      \u003ctd\u003e26\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\n\n\n\n```python\nfeat_info.info()\n```\n\n    \u003cclass 'pandas.core.frame.DataFrame'\u003e\n    RangeIndex: 85 entries, 0 to 84\n    Data columns (total 4 columns):\n     #   Column              Non-Null Count  Dtype \n    ---  ------              --------------  ----- \n     0   attribute           85 non-null     object\n     1   information_level   85 non-null     object\n     2   type                85 non-null     object\n     3   missing_or_unknown  85 non-null     object\n    dtypes: object(4)\n    memory usage: 2.8+ KB\n    \n\n\u003e **Tip**: Add additional cells to keep everything in reasonably-sized chunks! Keyboard shortcut `esc --\u003e a` (press escape to enter command mode, then press the 'A' key) adds a new cell before the active cell, and `esc --\u003e b` adds a new cell after the active cell. If you need to convert an active cell to a markdown cell, use `esc --\u003e m` and to convert to a code cell, use `esc --\u003e y`. \n\n## Step 1: Preprocessing\n\n### Step 1.1: Assess Missing Data\n\nThe feature summary file contains a summary of properties for each demographics data column. You will use this file to help you make cleaning decisions during this stage of the project. First of all, you should assess the demographics data in terms of missing data. Pay attention to the following points as you perform your analysis, and take notes on what you observe. Make sure that you fill in the **Discussion** cell with your findings and decisions at the end of each step that has one!\n\n#### Step 1.1.1: Convert Missing Value Codes to NaNs\nThe fourth column of the feature attributes summary (loaded in above as `feat_info`) documents the codes from the data dictionary that indicate missing or unknown data. While the file encodes this as a list (e.g. `[-1,0]`), this will get read in as a string object. You'll need to do a little bit of parsing to make use of it to identify and clean the data. Convert data that matches a 'missing' or 'unknown' value code into a numpy NaN value. You might want to see how much data takes on a 'missing' or 'unknown' code, and how much data is naturally missing, as a point of interest.\n\n**As one more reminder, you are encouraged to add additional cells to break up your analysis into manageable chunks.**\n\n\n```python\nazdias.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eAGER_TYP\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e6.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e5 rows × 85 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\nfeat_info.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eattribute\u003c/th\u003e\n      \u003cth\u003einformation_level\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003emissing_or_unknown\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003eAGER_TYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[-1,0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003eALTERSKATEGORIE_GROB\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1,0,9]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003eANREDE_KZ\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[-1,0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003eCJT_GESAMTTYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003eFINANZ_MINIMALIST\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1]\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\n\n\n\n```python\n# We dont do this inplace to keep idempotency, and to cache the values\nfeat_info['missing_or_unknown'] = feat_info['missing_or_unknown'].apply(lambda x: x[1:-1].split(','))\nfeat_info.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eattribute\u003c/th\u003e\n      \u003cth\u003einformation_level\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003emissing_or_unknown\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003eAGER_TYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[-1, 0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003eALTERSKATEGORIE_GROB\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1, 0, 9]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003eANREDE_KZ\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[-1, 0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003eCJT_GESAMTTYP\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003ecategorical\u003c/td\u003e\n      \u003ctd\u003e[0]\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003eFINANZ_MINIMALIST\u003c/td\u003e\n      \u003ctd\u003eperson\u003c/td\u003e\n      \u003ctd\u003eordinal\u003c/td\u003e\n      \u003ctd\u003e[-1]\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\n\n\n\n```python\ndef clean(x, name):\n    nan_indicators = feat_info[feat_info['attribute'] == name].iloc[0].missing_or_unknown\n    return x.map(lambda z: np.nan if str(z) in nan_indicators else z) \n```\n\n\n```python\n# This will run an operataion on each column, clean, which will then apply a map on the series to replace\n# any missing values with np.nan\nazdias_clean = azdias.apply(lambda x: clean(x, x.name), axis=0)\n```\n\n\n```python\nazdias_clean.head(10)\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eAGER_TYP\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e6.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e5\u003c/th\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e6\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e6.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e7\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e8\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e9\u003c/th\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e10 rows × 85 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n#### Step 1.1.2: Assess Missing Data in Each Column\n\nHow much missing data is present in each column? There are a few columns that are outliers in terms of the proportion of values that are missing. You will want to use matplotlib's [`hist()`](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html) function to visualize the distribution of missing value counts to find these columns. Identify and document these columns. While some of these columns might have justifications for keeping or re-encoding the data, for this project you should just remove them from the dataframe. (Feel free to make remarks about these outlier columns in the discussion, however!)\n\nFor the remaining features, are there any patterns in which columns have, or share, missing data?\n\n\n```python\n# Lets compare our original dataset, before cleaning\nazdias.isnull().sum()\n```\n\n\n\n\n    AGER_TYP                     0\n    ALTERSKATEGORIE_GROB         0\n    ANREDE_KZ                    0\n    CJT_GESAMTTYP             4854\n    FINANZ_MINIMALIST            0\n                             ...  \n    PLZ8_HHZ                116515\n    PLZ8_GBZ                116515\n    ARBEIT                   97216\n    ORTSGR_KLS9              97216\n    RELAT_AB                 97216\n    Length: 85, dtype: int64\n\n\n\n\n```python\n# And after cleaning, we can see we have successfully replaced missing/unknown\n# indicators with the correct np.nan values\nazdias_clean.isnull().sum()\n```\n\n\n\n\n    AGER_TYP                685843\n    ALTERSKATEGORIE_GROB      2881\n    ANREDE_KZ                    0\n    CJT_GESAMTTYP             4854\n    FINANZ_MINIMALIST            0\n                             ...  \n    PLZ8_HHZ                116515\n    PLZ8_GBZ                116515\n    ARBEIT                   97216\n    ORTSGR_KLS9              97216\n    RELAT_AB                 97216\n    Length: 85, dtype: int64\n\n\n\n\n```python\nnan_vals = azdias_clean.isnull().sum() / len(azdias_clean)\n```\n\n\n```python\n\nplt.hist(nan_vals * 100, bins=100)\nplt.ylabel('Missing Value')\nplt.show()\n```\n\n\n    \n![png](output_23_0.png)\n    \n\n\n\n```python\n#### Investigate patterns in the amount of missing data in each column.\n# credit to https://www.kaggle.com/cgump3rt/investigate-missing-values, for help with now to plot stuff.\nplt.figure(figsize=(16,8))\nplt.xticks(np.arange(len(nan_vals)) + 0.5, nan_vals.index, rotation='vertical')\nplt.ylabel('Nan Value')\nplt.bar(np.arange(len(nan_vals)), nan_vals)\n```\n\n\n\n\n    \u003cBarContainer object of 85 artists\u003e\n\n\n\n\n    \n![png](output_24_1.png)\n    \n\n\n\n```python\n# Remove the outlier columns from the dataset. (You'll perform other data\n# engineering tasks such as re-encoding and imputation later.)\ndrop_cols = ['AGER_TYP', 'GEBURTSJAHR', 'KK_KUNDENTYP']\nazdias_clean = azdias_clean.drop(columns=drop_cols)\n```\n\n#### Discussion 1.1.2: Assess Missing Data in Each Column\n\nUpon reviewing the data, both before and after our data cleaning, there are 3 observed columns that have a significant amount of missing data when compared to the rest of the features in the set.\n\n- AGER_TYP: This column has  rows, with **685843** values deemed missing or unknown, or **76.9554%**\n- GEBURTSJAHR: This column has 891221 rows, with **392318** values deemed missing or unknown, or **44.0202%**.\n- KK_KUNDENTYP: This column has 891221 rows, with **584612** values deemed missing or unknown, or **65.5967%**.\n\nWith these columns having such a large amount of data irrelevant, we can disregard these columns as to not influence our results negativly.\n\n\n```python\nazdias_clean.describe()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003eFINANZTYP\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003ecount\u003c/th\u003e\n      \u003ctd\u003e888340.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e886367.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e891221.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e774706.000000\u003c/td\u003e\n      \u003ctd\u003e794005.000000\u003c/td\u003e\n      \u003ctd\u003e794005.000000\u003c/td\u003e\n      \u003ctd\u003e794005.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003emean\u003c/th\u003e\n      \u003ctd\u003e2.757217\u003c/td\u003e\n      \u003ctd\u003e1.522098\u003c/td\u003e\n      \u003ctd\u003e3.632838\u003c/td\u003e\n      \u003ctd\u003e3.074528\u003c/td\u003e\n      \u003ctd\u003e2.821039\u003c/td\u003e\n      \u003ctd\u003e3.401106\u003c/td\u003e\n      \u003ctd\u003e3.033328\u003c/td\u003e\n      \u003ctd\u003e2.874167\u003c/td\u003e\n      \u003ctd\u003e3.075121\u003c/td\u003e\n      \u003ctd\u003e3.790586\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.253330\u003c/td\u003e\n      \u003ctd\u003e2.801858\u003c/td\u003e\n      \u003ctd\u003e1.595426\u003c/td\u003e\n      \u003ctd\u003e0.699166\u003c/td\u003e\n      \u003ctd\u003e1.943913\u003c/td\u003e\n      \u003ctd\u003e3.612821\u003c/td\u003e\n      \u003ctd\u003e3.381087\u003c/td\u003e\n      \u003ctd\u003e3.167854\u003c/td\u003e\n      \u003ctd\u003e5.293002\u003c/td\u003e\n      \u003ctd\u003e3.07222\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003estd\u003c/th\u003e\n      \u003ctd\u003e1.009951\u003c/td\u003e\n      \u003ctd\u003e0.499512\u003c/td\u003e\n      \u003ctd\u003e1.595021\u003c/td\u003e\n      \u003ctd\u003e1.321055\u003c/td\u003e\n      \u003ctd\u003e1.464749\u003c/td\u003e\n      \u003ctd\u003e1.322134\u003c/td\u003e\n      \u003ctd\u003e1.529603\u003c/td\u003e\n      \u003ctd\u003e1.486731\u003c/td\u003e\n      \u003ctd\u003e1.353248\u003c/td\u003e\n      \u003ctd\u003e1.987876\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.972008\u003c/td\u003e\n      \u003ctd\u003e0.920309\u003c/td\u003e\n      \u003ctd\u003e0.986736\u003c/td\u003e\n      \u003ctd\u003e0.727137\u003c/td\u003e\n      \u003ctd\u003e1.459654\u003c/td\u003e\n      \u003ctd\u003e0.973967\u003c/td\u003e\n      \u003ctd\u003e1.111598\u003c/td\u003e\n      \u003ctd\u003e1.002376\u003c/td\u003e\n      \u003ctd\u003e2.303739\u003c/td\u003e\n      \u003ctd\u003e1.36298\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003emin\u003c/th\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e1.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e25%\u003c/th\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e0.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e2.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e50%\u003c/th\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e3.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e75%\u003c/th\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e6.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e1.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e7.000000\u003c/td\u003e\n      \u003ctd\u003e4.00000\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003emax\u003c/th\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e6.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e6.000000\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e4.000000\u003c/td\u003e\n      \u003ctd\u003e3.000000\u003c/td\u003e\n      \u003ctd\u003e2.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e5.000000\u003c/td\u003e\n      \u003ctd\u003e9.000000\u003c/td\u003e\n      \u003ctd\u003e9.000000\u003c/td\u003e\n      \u003ctd\u003e9.00000\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e8 rows × 78 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n#### Step 1.1.3: Assess Missing Data in Each Row\n\nNow, you'll perform a similar assessment for the rows of the dataset. How much data is missing in each row? As with the columns, you should see some groups of points that have a very different numbers of missing values. Divide the data into two subsets: one for data points that are above some threshold for missing values, and a second subset for points below that threshold.\n\nIn order to know what to do with the outlier rows, we should see if the distribution of data values on columns that are not missing data (or are missing very little data) are similar or different between the two groups. Select at least five of these columns and compare the distribution of values.\n- You can use seaborn's [`countplot()`](https://seaborn.pydata.org/generated/seaborn.countplot.html) function to create a bar chart of code frequencies and matplotlib's [`subplot()`](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplot.html) function to put bar charts for the two subplots side by side.\n- To reduce repeated code, you might want to write a function that can perform this comparison, taking as one of its arguments a column to be compared.\n\nDepending on what you observe in your comparison, this will have implications on how you approach your conclusions later in the analysis. If the distributions of non-missing features look similar between the data with many missing values and the data with few or no missing values, then we could argue that simply dropping those points from the analysis won't present a major issue. On the other hand, if the data with many missing values looks very different from the data with few or no missing values, then we should make a note on those data as special. We'll revisit these data later on. **Either way, you should continue your analysis for now using just the subset of the data with few or no missing values.**\n\n\n```python\n azdias_clean.isnull().sum(axis=1)\n```\n\n\n\n\n    0         46\n    1          0\n    2          0\n    3          1\n    4          0\n              ..\n    891216     3\n    891217     4\n    891218     1\n    891219     0\n    891220     0\n    Length: 891221, dtype: int64\n\n\n\n\n```python\n# How much data is missing in each row of the dataset?\nnull_values = azdias_clean.isnull().sum(axis=1)\n\nplt.figure(figsize=(15,4))\nplt.hist(null_values)\nplt.ylabel('Rows')\nplt.xlabel('Missing Values')\nplt.show()\n```\n\n\n    \n![png](output_30_0.png)\n    \n\n\n\n```python\nprint('Null Counts Less than threshold')\nprint('---')\nprint(' \u003c= 2')\nprint((azdias.isnull().sum(axis=1) \u003c= 2).value_counts())\nprint('--')\nprint(' \u003c= 3')\nprint((azdias.isnull().sum(axis=1) \u003c= 3).value_counts())\nprint('--')\nprint(' \u003c= 4')\nprint((azdias.isnull().sum(axis=1) \u003c= 4).value_counts())\nprint('--')\nprint(' \u003c= 5')\nprint((azdias.isnull().sum(axis=1) \u003c= 5).value_counts())\nprint('--')\nprint(' \u003c= 6')\nprint((azdias.isnull().sum(axis=1) \u003c= 6).value_counts())\nprint('--')\nprint(' \u003c= 7')\nprint((azdias.isnull().sum(axis=1) \u003c= 7).value_counts())\nprint('--')\n```\n\n    Null Counts Less than threshold\n    ---\n     \u003c= 2\n    True     730306\n    False    160915\n    dtype: int64\n    --\n     \u003c= 3\n    True     738373\n    False    152848\n    dtype: int64\n    --\n     \u003c= 4\n    True     743518\n    False    147703\n    dtype: int64\n    --\n     \u003c= 5\n    True     743870\n    False    147351\n    dtype: int64\n    --\n     \u003c= 6\n    True     743997\n    False    147224\n    dtype: int64\n    --\n     \u003c= 7\n    True     752162\n    False    139059\n    dtype: int64\n    --\n    \n\n### Analysis\n\nBased on our above graph, of rows with missing values, we can divide our data based on having \u003c= 10 null values per row and those that are greater.\n\n\n```python\n# Write code to divide the data into two subsets based on the number of missing\n# values in each row.\n\nazdias_lt = azdias_clean[azdias_clean.isnull().sum(axis=1) \u003c= 10]\nazdias_gt = azdias_clean[azdias_clean.isnull().sum(axis=1) \u003e 10]\n\n```\n\n\n```python\nazdias_clean_missing_mask = (azdias_clean.isnull().sum() / len(azdias_clean)) * 100\n```\n\n\n```python\nrandom_columns = np.random.choice(azdias_clean.columns, size = (5,))\nplot_index = 1\nplt.figure(figsize = (16, 16))\n\nfor c in random_columns:\n    plt.subplot(5, 2, plot_index)\n    sns.countplot(azdias_gt[c])\n    \n    if plot_index == 1:\n        plt.title('Data with High Freq Missing Values')\n    \n    plt.subplot(5, 2, plot_index + 1)\n    sns.countplot(azdias_lt[c])\n    \n    if plot_index == 1:\n        plt.title('Data with Low Freq Missing Values')\n    \n    plot_index += 2\n```\n\n\n    \n![png](output_35_0.png)\n    \n\n\n#### Discussion 1.1.3: Assess Missing Data in Each Row\n\nThe 'Missing Values' histogram plot above is displaying missing features per row.  We can cleary see that there is large porportion of rows that have 10 or less missing columns.  Although we could limit this to 5 I think that 10 should give us a clear picture of the data at hand, given that there are 78 feature columns in out dataset.  \n\n\n### Step 1.2: Select and Re-Encode Features\n\nChecking for missing data isn't the only way in which you can prepare a dataset for analysis. Since the unsupervised learning techniques to be used will only work on data that is encoded numerically, you need to make a few encoding changes or additional assumptions to be able to make progress. In addition, while almost all of the values in the dataset are encoded using numbers, not all of them represent numeric values. Check the third column of the feature summary (`feat_info`) for a summary of types of measurement.\n- For numeric and interval data, these features can be kept without changes.\n- Most of the variables in the dataset are ordinal in nature. While ordinal values may technically be non-linear in spacing, make the simplifying assumption that the ordinal variables can be treated as being interval in nature (that is, kept without any changes).\n- Special handling may be necessary for the remaining two variable types: categorical, and 'mixed'.\n\nIn the first two parts of this sub-step, you will perform an investigation of the categorical and mixed-type features and make a decision on each of them, whether you will keep, drop, or re-encode each. Then, in the last part, you will create a new data frame with only the selected and engineered columns.\n\nData wrangling is often the trickiest part of the data analysis process, and there's a lot of it to be done here. But stick with it: once you're done with this step, you'll be ready to get to the machine learning parts of the project!\n\n\n```python\n# How many features are there of each data type?\nfeat_info['type'].value_counts()\n```\n\n\n\n\n    ordinal        49\n    categorical    21\n    numeric         7\n    mixed           7\n    interval        1\n    Name: type, dtype: int64\n\n\n\n#### Step 1.2.1: Re-Encode Categorical Features\n\nFor categorical data, you would ordinarily need to encode the levels as dummy variables. Depending on the number of categories, perform one of the following:\n- For binary (two-level) categoricals that take numeric values, you can keep them without needing to do anything.\n- There is one binary variable that takes on non-numeric values. For this one, you need to re-encode the values as numbers or create a dummy variable.\n- For multi-level categoricals (three or more values), you can choose to encode the values using multiple dummy variables (e.g. via [OneHotEncoder](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html)), or (to keep things straightforward) just drop them from the analysis. As always, document your choices in the Discussion section.\n\n\n```python\n#azdias_formatted = azdias_clean.copy(deep=True)\n\n# We will be using our data that we defined to have few mising values\nazdias_formatted = azdias_lt.copy(deep=True)\n```\n\n\n```python\nazdias_formatted.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003eFINANZTYP\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e6\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e6.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e5\u003c/th\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e5 rows × 82 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\n# Assess categorical variables: which are binary, which are multi-level, and\n# which one needs to be re-encoded?\n\n# Get a subset of our feature columns that are known of type categorical\ncategorical_columns = feat_info[feat_info['type'] == 'categorical']['attribute'].values\n```\n\n\n```python\ncategorical_columns\n```\n\n\n\n\n    array(['AGER_TYP', 'ANREDE_KZ', 'CJT_GESAMTTYP', 'FINANZTYP',\n           'GFK_URLAUBERTYP', 'GREEN_AVANTGARDE', 'LP_FAMILIE_FEIN',\n           'LP_FAMILIE_GROB', 'LP_STATUS_FEIN', 'LP_STATUS_GROB',\n           'NATIONALITAET_KZ', 'SHOPPER_TYP', 'SOHO_KZ', 'TITEL_KZ',\n           'VERS_TYP', 'ZABEOTYP', 'KK_KUNDENTYP', 'GEBAEUDETYP',\n           'OST_WEST_KZ', 'CAMEO_DEUG_2015', 'CAMEO_DEU_2015'], dtype=object)\n\n\n\n\n```python\ncat_types = {\n    'binary': [],\n    'multi-level': []\n}\n```\n\n\n```python\n# Re-encode categorical variable(s) to be kept in the analysis.\n\nfor c in categorical_columns:\n    if not c in azdias_formatted:\n        continue\n    if azdias_formatted[c].nunique() == 2:\n        cat_types['binary'].append(c)\n    else:\n        cat_types['multi-level'].append(c)\n```\n\n\n```python\n# Print our divided columns\nprint(f'Binary {cat_types[\"binary\"]}')\nprint('')\nprint(f'multi-level {cat_types[\"multi-level\"]}')\n```\n\n    Binary ['ANREDE_KZ', 'GREEN_AVANTGARDE', 'SOHO_KZ', 'VERS_TYP', 'OST_WEST_KZ']\n    \n    multi-level ['CJT_GESAMTTYP', 'FINANZTYP', 'GFK_URLAUBERTYP', 'LP_FAMILIE_FEIN', 'LP_FAMILIE_GROB', 'LP_STATUS_FEIN', 'LP_STATUS_GROB', 'NATIONALITAET_KZ', 'SHOPPER_TYP', 'TITEL_KZ', 'ZABEOTYP', 'GEBAEUDETYP', 'CAMEO_DEUG_2015', 'CAMEO_DEU_2015']\n    \n\n\n```python\n[azdias_formatted[c].value_counts() for c in cat_types['binary']]\n```\n\n\n\n\n    [2    407322\n     1    374077\n     Name: ANREDE_KZ, dtype: int64,\n     0    609569\n     1    171830\n     Name: GREEN_AVANTGARDE, dtype: int64,\n     0.0    774837\n     1.0      6562\n     Name: SOHO_KZ, dtype: int64,\n     2.0    389981\n     1.0    356813\n     Name: VERS_TYP, dtype: int64,\n     W    615734\n     O    165665\n     Name: OST_WEST_KZ, dtype: int64]\n\n\n\n\n```python\nazdias_formatted['OST_WEST_KZ'].isnull().sum()\n```\n\n\n\n\n    0\n\n\n\n\n```python\nazdias_formatted.shape\n```\n\n\n\n\n    (781399, 82)\n\n\n\n\n```python\n# Once reviewing our binary features, there is 1 that is binary in nature but with non numerical data, OST_WEST_KZ\n# We can onehot encode this column\nprint(azdias_formatted['OST_WEST_KZ'].value_counts())\n```\n\n    1    615734\n    0    165665\n    Name: OST_WEST_KZ, dtype: int64\n    \n\n\n```python\nazdias_formatted['OST_WEST_KZ'].replace([\"W\", \"O\"], [1, 0], inplace=True)\n\n```\n\n## Encoding Multi-Level Cateogorial Data\n\n\n```python\n# Lets remove cols we have already dropped\nmulti_cats = [x for x in cat_types['multi-level'] if x in azdias_formatted]\n\nazdias_formatted = pd.get_dummies(data=azdias_formatted, columns=multi_cats, prefix=multi_cats)\n```\n\n\n```python\n# Here we have a full dataframe with our one-hot encoded features.\nazdias_formatted.info()\n```\n\n    \u003cclass 'pandas.core.frame.DataFrame'\u003e\n    Int64Index: 781399 entries, 1 to 891220\n    Columns: 204 entries, ALTERSKATEGORIE_GROB to CAMEO_DEU_2015_9E\n    dtypes: float64(44), int64(23), object(1), uint8(136)\n    memory usage: 512.7+ MB\n    \n\n\n```python\nazdias_formatted['LP_STATUS_GROB_2.0']\n```\n\n\n\n\n    1         0\n    2         1\n    3         0\n    4         1\n    5         1\n             ..\n    891216    0\n    891217    0\n    891218    1\n    891219    0\n    891220    0\n    Name: LP_STATUS_GROB_2.0, Length: 781399, dtype: uint8\n\n\n\n----\n\n#### Discussion 1.2.1: Re-Encode Categorical Features\n\nWe have `10` binary categorical features and `30` multi level categorical features.  Of these `10` binary features, `1` was a non numerical features, 'OST_WEST_KZ'.  For this we mapped its values W, O to 1 and 0 respectivly.  \n\nAs for the multi-level categorical features, we also performed one hot encoding on these as well.  We then dropped the original columns from the dataset.  My goal was to perserve as much as the data initially as we can, so I did not drop any of the categorical columns at this time, outside of the original columns once they have been one hot encoded.  If there proves to be an issue with any of these columns we can go back and remove them as necessary.\n\n#### Step 1.2.2: Engineer Mixed-Type Features\n\nThere are a handful of features that are marked as \"mixed\" in the feature summary that require special treatment in order to be included in the analysis. There are two in particular that deserve attention; the handling of the rest are up to your own choices:\n- \"PRAEGENDE_JUGENDJAHRE\" combines information on three dimensions: generation by decade, movement (mainstream vs. avantgarde), and nation (east vs. west). While there aren't enough levels to disentangle east from west, you should create two new variables to capture the other two dimensions: an interval-type variable for decade, and a binary variable for movement.\n- \"CAMEO_INTL_2015\" combines information on two axes: wealth and life stage. Break up the two-digit codes by their 'tens'-place and 'ones'-place digits into two new ordinal variables (which, for the purposes of this project, is equivalent to just treating them as their raw numeric values).\n- If you decide to keep or engineer new features around the other mixed-type features, make sure you note your steps in the Discussion section.\n\nBe sure to check `Data_Dictionary.md` for the details needed to finish these tasks.\n\n\n```python\nazdias_formatted.shape\n```\n\n\n\n\n    (781399, 204)\n\n\n\n\n```python\n# Investigate \"PRAEGENDE_JUGENDJAHRE\" and engineer two new variables.\n# 1 var for generation (40s, 50s, 60s) and one for movement (avant, main)\n\n# Dominating movement of person's youth (avantgarde vs. mainstream; east vs. west)\n# - -1: unknown\n# -  0: unknown\n# -  1: 40s - war years (Mainstream, E+W)\n# -  2: 40s - reconstruction years (Avantgarde, E+W)\n# -  3: 50s - economic miracle (Mainstream, E+W)\n# -  4: 50s - milk bar / Individualisation (Avantgarde, E+W)\n# -  5: 60s - economic miracle (Mainstream, E+W)\n# -  6: 60s - generation 68 / student protestors (Avantgarde, W)\n# -  7: 60s - opponents to the building of the Wall (Avantgarde, E)\n# -  8: 70s - family orientation (Mainstream, E+W)\n# -  9: 70s - peace movement (Avantgarde, E+W)\n# - 10: 80s - Generation Golf (Mainstream, W)\n# - 11: 80s - ecological awareness (Avantgarde, W)\n# - 12: 80s - FDJ / communist party youth organisation (Mainstream, E)\n# - 13: 80s - Swords into ploughshares (Avantgarde, E)\n# - 14: 90s - digital media kids (Mainstream, E+W)\n# - 15: 90s - ecological awareness (Avantgarde, E+W)\n\nAVANT, MAIN = 1, 2\nforty, fifty, sixty, seventy, eighty, ninty = 1, 2, 3, 4, 5, 6\n\ngeneration = { \n    1: (forty, MAIN), 2: (forty, AVANT), 3: (fifty, MAIN), 4: (fifty, AVANT), 5: (sixty, MAIN),\n    6: (sixty, AVANT), 7: (sixty, AVANT), 8: (seventy, MAIN), 9: (seventy, AVANT), 10: (eighty, MAIN),\n    11: (eighty, AVANT), 12: (eighty, MAIN), 13: (eighty, AVANT), 14: (ninty, MAIN), 15: (ninty, AVANT)\n             }\n\ndef map_praegende_gen(value):\n    if value in generation:\n        return generation[int(value)][0]\n    \ndef map_praegende_movement(value):\n    if value in generation:\n        return generation[int(value)][1]\n\n```\n\n\n```python\nazdias_formatted['PRAEGENDE_JUGENDJAHRE'].value_counts()\n```\n\n\n\n\n    14.0    178663\n    8.0     138903\n    10.0     83974\n    5.0      83740\n    3.0      53177\n    15.0     41067\n    11.0     34668\n    9.0      33228\n    6.0      25531\n    12.0     24059\n    4.0      20353\n    1.0      20350\n    2.0       7454\n    13.0      5562\n    7.0       3967\n    Name: PRAEGENDE_JUGENDJAHRE, dtype: int64\n\n\n\n\n```python\nazdias_formatted['PRAEGENDE_JUGENDJAHRE_GENERATION'] = azdias_formatted['PRAEGENDE_JUGENDJAHRE'].apply(map_praegende_gen)\nazdias_formatted['PRAEGENDE_JUGENDJAHRE_MOVEMENT'] = azdias_formatted['PRAEGENDE_JUGENDJAHRE'].apply(map_praegende_movement)\n\n\n```\n\n\n```python\nazdias_formatted['PRAEGENDE_JUGENDJAHRE_MOVEMENT'].isnull().sum()\n```\n\n\n\n\n    26703\n\n\n\n\n```python\n# Investigate \"CAMEO_INTL_2015\" and engineer two new variables.\nazdias_formatted['CAMEO_INTL_2015'].value_counts()\n\nwealthy, prosp, comfort, less_aff, poor = 1, 2, 3, 4, 5\npre_fam, young_cou, fam, old, eld = 1, 2, 3, 4, 5\n\ndef format_cameo_value(val):\n    if pd.isnull(val):\n        return\n    return int(val) // 10**1 % 10\n\ndef format_cameo_family_type(val):\n    if pd.isnull(val):\n        return\n    return int(val) // 10**0 % 10\n\nformat_cameo_value(np.nan)\n```\n\n\n```python\nazdias_formatted['CAMEO_INTL_2015_WEALTH'] = azdias_formatted['CAMEO_INTL_2015'].apply(format_cameo_value)\nazdias_formatted['CAMEO_INTL_2015_LIFESTAGE'] = azdias_formatted['CAMEO_INTL_2015'].apply(format_cameo_family_type)\n\nazdias_formatted['CAMEO_INTL_2015_LIFESTAGE'].value_counts()\n```\n\n\n\n\n    1.0    242082\n    4.0    228775\n    3.0    115581\n    5.0    115403\n    2.0     75825\n    Name: CAMEO_INTL_2015_LIFESTAGE, dtype: int64\n\n\n\n\n```python\nazdias_formatted = azdias_formatted.drop(columns=['CAMEO_INTL_2015', 'PRAEGENDE_JUGENDJAHRE'])\n```\n\n#### Discussion 1.2.2: Engineer Mixed-Type Features\n\n\nWe have 2 features in our data set that are mixed type features, these are PRAEGENDE_JUGENDJAHRE and CAMEO_INTL_2015.  By having sufficient information on how to map these values to relevant data, we were able to encode both these features into 4 new features, 2 and 2 respectivly.  We were able to map these new feature columns using `apply()` function of the dataframe to apply a function to each column series.  \n\n\n#### Step 1.2.3: Complete Feature Selection\n\nIn order to finish this step up, you need to make sure that your data frame now only has the columns that you want to keep. To summarize, the dataframe should consist of the following:\n- All numeric, interval, and ordinal type columns from the original dataset.\n- Binary categorical features (all numerically-encoded).\n- Engineered features from other multi-level categorical features and mixed features.\n\nMake sure that for any new columns that you have engineered, that you've excluded the original columns from the final dataset. Otherwise, their values will interfere with the analysis later on the project. For example, you should not keep \"PRAEGENDE_JUGENDJAHRE\", since its values won't be useful for the algorithm: only the values derived from it in the engineered features you created should be retained. As a reminder, your data should only be from **the subset with few or no missing values**.\n\n\n```python\n# If there are other re-engineering tasks you need to perform, make sure you\n# take care of them here. (Dealing with missing data will come in step 2.1.)\nprint(azdias_formatted.info())\nprint(f'Value Types in our Data: {np.unique(azdias_formatted.dtypes.values)}')\n```\n\n    \u003cclass 'pandas.core.frame.DataFrame'\u003e\n    Int64Index: 781399 entries, 1 to 891220\n    Columns: 206 entries, ALTERSKATEGORIE_GROB to CAMEO_INTL_2015_LIFESTAGE\n    dtypes: float64(47), int64(23), uint8(136)\n    memory usage: 524.6 MB\n    None\n    Value Types in our Data: [dtype('uint8') dtype('int64') dtype('float64')]\n    \n\n### Step 1.3: Create a Cleaning Function\n\nEven though you've finished cleaning up the general population demographics data, it's important to look ahead to the future and realize that you'll need to perform the same cleaning steps on the customer demographics data. In this substep, complete the function below to execute the main feature selection, encoding, and re-engineering steps you performed above. Then, when it comes to looking at the customer data in Step 3, you can just run this function on that DataFrame to get the trimmed dataset in a single step.\n\n\n```python\ndef clean_attr2(x, name):\n    attr = feat_info[feat_info['attribute'] == name]\n    \n    # if the row DNE, return early\n    if len(attr) == 0:\n        return\n    \n    nan_indicators = attr.iloc[0].missing_or_unknown\n    return x.map(lambda z: np.nan if str(z) in nan_indicators else z) \n```\n\n\n```python\ndef clean_data2(df):\n    \"\"\"\n    Perform feature trimming, re-encoding, and engineering for demographics\n    data\n    \n    INPUT: Demographics DataFrame\n    OUTPUT: Trimmed and cleaned demographics DataFrame\n    \"\"\"\n    \n    # Put in code here to execute all main cleaning steps:\n    # convert missing value codes into NaNs, ...\n    df = df.apply(lambda x: clean_attr2(x, x.name), axis=0)\n    \n    # remove selected columns and rows, ...\n    drop_cols = ['AGER_TYP', 'GEBURTSJAHR', 'KK_KUNDENTYP']\n    df = df.drop(columns=drop_cols)\n    \n    # Limit our data to rows with few missing features\n    # df = df[df.isnull().sum(axis=1) \u003e 10]\n\n    # select, re-encode, and engineer column values.\n    categorical_columns = feat_info[feat_info['type'] == 'categorical']['attribute'].values\n    cat_types = {\n        'binary': [],\n        'multi-level': []\n    }\n    for c in categorical_columns:\n        if not c in df:\n            continue\n        if df[c].nunique() == 2:\n            cat_types['binary'].append(c)\n        else:\n            cat_types['multi-level'].append(c)\n    \n    df['OST_WEST_KZ'].replace([\"W\", \"O\"], [1, 0], inplace=True)  \n    \n    # Lets remove cols we have already dropped\n    multi_cats = [x for x in cat_types['multi-level'] if x in df]\n\n    df = pd.get_dummies(data=df, columns=multi_cats, prefix=multi_cats)\n    \n    # Process our 2 multi level features\n    df['PRAEGENDE_JUGENDJAHRE_GENERATION'] = df['PRAEGENDE_JUGENDJAHRE'].apply(map_praegende_gen)\n    df['PRAEGENDE_JUGENDJAHRE_MOVEMENT'] = df['PRAEGENDE_JUGENDJAHRE'].apply(map_praegende_movement)\n    \n    df['CAMEO_INTL_2015_WEALTH'] = df['CAMEO_INTL_2015'].apply(format_cameo_value)\n    df['CAMEO_INTL_2015_LIFESTAGE'] = df['CAMEO_INTL_2015'].apply(format_cameo_family_type)\n    \n    df = df.drop(columns=['PRAEGENDE_JUGENDJAHRE', 'CAMEO_INTL_2015'])\n\n    # Return the cleaned dataframe.\n    return df    \n```\n\n## Step 2: Feature Transformation\n\n### Step 2.1: Apply Feature Scaling\n\nBefore we apply dimensionality reduction techniques to the data, we need to perform feature scaling so that the principal component vectors are not influenced by the natural differences in scale for features. Starting from this part of the project, you'll want to keep an eye on the [API reference page for sklearn](http://scikit-learn.org/stable/modules/classes.html) to help you navigate to all of the classes and functions that you'll need. In this substep, you'll need to check the following:\n\n- sklearn requires that data not have missing values in order for its estimators to work properly. So, before applying the scaler to your data, make sure that you've cleaned the DataFrame of the remaining missing values. This can be as simple as just removing all data points with missing data, or applying an [Imputer](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.Imputer.html) to replace all missing values. You might also try a more complicated procedure where you temporarily remove missing values in order to compute the scaling parameters before re-introducing those missing values and applying imputation. Think about how much missing data you have and what possible effects each approach might have on your analysis, and justify your decision in the discussion section below.\n- For the actual scaling function, a [StandardScaler](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html) instance is suggested, scaling each feature to mean 0 and standard deviation 1.\n- For these classes, you can make use of the `.fit_transform()` method to both fit a procedure to the data as well as apply the transformation to the data at the same time. Don't forget to keep the fit sklearn objects handy, since you'll be applying them to the customer demographics data towards the end of the project.\n\n\n```python\n# If you've not yet cleaned the dataset of all NaN values, then investigate and\n# do that now.\n\n# For now, we are going to drop rows with missing data\n# azdias_formatted = azdias_formatted.dropna()\n\nazdias = azdias_formatted.loc[:,~azdias_formatted.columns.duplicated()]\n\n\nimputer = SimpleImputer(strategy='median')\nimputer_data = imputer.fit_transform(azdias)\n```\n\n\n```python\nazdias.shape\n```\n\n\n\n\n    (781399, 206)\n\n\n\n\n```python\n# Apply feature scaling to the general population demographics data.\nscaler = StandardScaler()\nstandardized_data = scaler.fit_transform(imputer_data)\n```\n\n### Discussion 2.1: Apply Feature Scaling\n\n~~When it comes to missing data, I opted for the quick approach of dropping data with missing values~~.  \n\nUpon nearing the final conclusion of this notebook, I had to come back here and make some adjustments.  I originally opted to drop rows with missing data, but after further review I used SimpleImputer instead.\n\nThis is a first attempt to get to the point where we are starting to look at our data points.  ~~Using an Imputer is not out of the realm of possibility at this point, but I opted for simpler.~~\n\n### Step 2.2: Perform Dimensionality Reduction\n\nOn your scaled data, you are now ready to apply dimensionality reduction techniques.\n\n- Use sklearn's [PCA](http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html) class to apply principal component analysis on the data, thus finding the vectors of maximal variance in the data. To start, you should not set any parameters (so all components are computed) or set a number of components that is at least half the number of features (so there's enough features to see the general trend in variability).\n- Check out the ratio of variance explained by each principal component as well as the cumulative variance explained. Try plotting the cumulative or sequential values using matplotlib's [`plot()`](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html) function. Based on what you find, select a value for the number of transformed features you'll retain for the clustering part of the project.\n- Once you've made a choice for the number of components to keep, make sure you re-fit a PCA instance to perform the decided-on transformation.\n\n\n```python\n# Apply PCA to the data.\npca = PCA()\npca_features = pca.fit_transform(standardized_data)\n```\n\n\n```python\nlen(pca.components_)\n```\n\n\n\n\n    206\n\n\n\n\n```python\n# Investigate the variance accounted for by each principal component.\nplt.plot(np.cumsum(pca.explained_variance_ratio_))\nplt.xlabel('Number of Components')\nplt.ylabel('Explained Varianve')\nplt.title('Explained Variance Per Principal Component: 206 Components')\n```\n\n\n\n\n    Text(0.5, 1.0, 'Explained Variance Per Principal Component: 206 Components')\n\n\n\n\n    \n![png](output_81_1.png)\n    \n\n\n\n```python\n# Re-apply PCA to the data while selecting for number of components to retain.\npca_100 = PCA(100)\nX_pca_100 = pca_100.fit_transform(standardized_data)\n```\n\n\n```python\n# What is our total variance with 100 components?\nprint(sum(pca_100.explained_variance_ratio_ * 100))\n```\n\n    84.66528411500116\n    \n\n\n```python\n# Investigate the variance accounted for by each principal component.\n#scree_plot(pca, 'Explained Variance Per Principal Component: 100/205')\n\nplt.plot(np.cumsum(pca_100.explained_variance_ratio_))\nplt.xlabel('Number of Components')\nplt.ylabel('Explained Varianve')\nplt.title('Explained Variance Per Principal Component: 100 Components')\n```\n\n\n\n\n    Text(0.5, 1.0, 'Explained Variance Per Principal Component: 100 Components')\n\n\n\n\n    \n![png](output_84_1.png)\n    \n\n\n\n```python\nplt.figure(figsize=(10,7))\nplt.plot(X_pca_100)\nplt.xlabel('Observation')\nplt.ylabel('Transformed Data')\nplt.title('Scaled Data by PCA: ~84%', pad=10)\n```\n\n\n\n\n    Text(0.5, 1.0, 'Scaled Data by PCA: ~84%')\n\n\n\n\n    \n![png](output_85_1.png)\n    \n\n\n## For sake of curiosity\n\n\n```python\npca_2 = PCA(n_components=2)\nX_pca_2 = pca_2.fit_transform(standardized_data)\nprint(sum(pca_2.explained_variance_ratio_ * 100))\n```\n\n    13.544393370488944\n    \n\n### Discussion 2.2: Perform Dimensionality Reduction\n\n\nAfter performing PCA on our dataset, we identified 477 components.  By reducing this down to 100 out of the original 477 we can still maintain about 84.81% explained variance.\n\n### Step 2.3: Interpret Principal Components\n\nNow that we have our transformed principal components, it's a nice idea to check out the weight of each variable on the first few components to see if they can be interpreted in some fashion.\n\nAs a reminder, each principal component is a unit vector that points in the direction of highest variance (after accounting for the variance captured by earlier principal components). The further a weight is from zero, the more the principal component is in the direction of the corresponding feature. If two features have large weights of the same sign (both positive or both negative), then increases in one tend expect to be associated with increases in the other. To contrast, features with different signs can be expected to show a negative correlation: increases in one variable should result in a decrease in the other.\n\n- To investigate the features, you should map each weight to their corresponding feature name, then sort the features according to weight. The most interesting features for each principal component, then, will be those at the beginning and end of the sorted list. Use the data dictionary document to help you understand these most prominent features, their relationships, and what a positive or negative value on the principal component might indicate.\n- You should investigate and interpret feature associations from the first three principal components in this substep. To help facilitate this, you should write a function that you can call at any time to print the sorted list of feature weights, for the *i*-th principal component. This might come in handy in the next step of the project, when you interpret the tendencies of the discovered clusters.\n\n\n```python\ndf = pd.DataFrame(np.round(pca_100.components_, 4), columns=azdias.keys())\ndf.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003eGREEN_AVANTGARDE\u003c/th\u003e\n      \u003cth\u003eHEALTH_TYP\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_8D\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9A\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9B\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9C\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9D\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9E\u003c/th\u003e\n      \u003cth\u003ePRAEGENDE_JUGENDJAHRE_GENERATION\u003c/th\u003e\n      \u003cth\u003ePRAEGENDE_JUGENDJAHRE_MOVEMENT\u003c/th\u003e\n      \u003cth\u003eCAMEO_INTL_2015_WEALTH\u003c/th\u003e\n      \u003cth\u003eCAMEO_INTL_2015_LIFESTAGE\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003e-0.0678\u003c/td\u003e\n      \u003ctd\u003e0.0137\u003c/td\u003e\n      \u003ctd\u003e-0.1770\u003c/td\u003e\n      \u003ctd\u003e0.0978\u003c/td\u003e\n      \u003ctd\u003e-0.0688\u003c/td\u003e\n      \u003ctd\u003e0.0398\u003c/td\u003e\n      \u003ctd\u003e0.0405\u003c/td\u003e\n      \u003ctd\u003e0.1462\u003c/td\u003e\n      \u003ctd\u003e-0.0988\u003c/td\u003e\n      \u003ctd\u003e0.0189\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.0257\u003c/td\u003e\n      \u003ctd\u003e0.0351\u003c/td\u003e\n      \u003ctd\u003e0.0546\u003c/td\u003e\n      \u003ctd\u003e0.0563\u003c/td\u003e\n      \u003ctd\u003e0.0556\u003c/td\u003e\n      \u003ctd\u003e0.0182\u003c/td\u003e\n      \u003ctd\u003e0.0558\u003c/td\u003e\n      \u003ctd\u003e0.0988\u003c/td\u003e\n      \u003ctd\u003e0.1782\u003c/td\u003e\n      \u003ctd\u003e-0.1046\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003e0.2369\u003c/td\u003e\n      \u003ctd\u003e0.0357\u003c/td\u003e\n      \u003ctd\u003e0.1039\u003c/td\u003e\n      \u003ctd\u003e-0.2334\u003c/td\u003e\n      \u003ctd\u003e0.2232\u003c/td\u003e\n      \u003ctd\u003e-0.2068\u003c/td\u003e\n      \u003ctd\u003e-0.2151\u003c/td\u003e\n      \u003ctd\u003e0.0713\u003c/td\u003e\n      \u003ctd\u003e0.0028\u003c/td\u003e\n      \u003ctd\u003e-0.0530\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.0322\u003c/td\u003e\n      \u003ctd\u003e-0.0102\u003c/td\u003e\n      \u003ctd\u003e-0.0026\u003c/td\u003e\n      \u003ctd\u003e0.0019\u003c/td\u003e\n      \u003ctd\u003e0.0078\u003c/td\u003e\n      \u003ctd\u003e0.0373\u003c/td\u003e\n      \u003ctd\u003e-0.2421\u003c/td\u003e\n      \u003ctd\u003e-0.0028\u003c/td\u003e\n      \u003ctd\u003e0.0404\u003c/td\u003e\n      \u003ctd\u003e0.0208\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003e0.0137\u003c/td\u003e\n      \u003ctd\u003e-0.3356\u003c/td\u003e\n      \u003ctd\u003e0.1316\u003c/td\u003e\n      \u003ctd\u003e-0.0551\u003c/td\u003e\n      \u003ctd\u003e0.0451\u003c/td\u003e\n      \u003ctd\u003e-0.1549\u003c/td\u003e\n      \u003ctd\u003e-0.0435\u003c/td\u003e\n      \u003ctd\u003e-0.0677\u003c/td\u003e\n      \u003ctd\u003e0.0960\u003c/td\u003e\n      \u003ctd\u003e-0.0041\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e-0.0006\u003c/td\u003e\n      \u003ctd\u003e-0.0034\u003c/td\u003e\n      \u003ctd\u003e0.0122\u003c/td\u003e\n      \u003ctd\u003e0.0253\u003c/td\u003e\n      \u003ctd\u003e0.0118\u003c/td\u003e\n      \u003ctd\u003e-0.0021\u003c/td\u003e\n      \u003ctd\u003e-0.0449\u003c/td\u003e\n      \u003ctd\u003e-0.0960\u003c/td\u003e\n      \u003ctd\u003e0.0129\u003c/td\u003e\n      \u003ctd\u003e-0.0136\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e-0.0056\u003c/td\u003e\n      \u003ctd\u003e0.1096\u003c/td\u003e\n      \u003ctd\u003e-0.0121\u003c/td\u003e\n      \u003ctd\u003e0.0026\u003c/td\u003e\n      \u003ctd\u003e-0.0043\u003c/td\u003e\n      \u003ctd\u003e-0.0305\u003c/td\u003e\n      \u003ctd\u003e0.0181\u003c/td\u003e\n      \u003ctd\u003e-0.0072\u003c/td\u003e\n      \u003ctd\u003e0.1904\u003c/td\u003e\n      \u003ctd\u003e-0.0079\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e-0.0024\u003c/td\u003e\n      \u003ctd\u003e0.0144\u003c/td\u003e\n      \u003ctd\u003e0.0032\u003c/td\u003e\n      \u003ctd\u003e0.0070\u003c/td\u003e\n      \u003ctd\u003e0.0052\u003c/td\u003e\n      \u003ctd\u003e0.0020\u003c/td\u003e\n      \u003ctd\u003e0.0243\u003c/td\u003e\n      \u003ctd\u003e-0.1904\u003c/td\u003e\n      \u003ctd\u003e-0.0122\u003c/td\u003e\n      \u003ctd\u003e0.0040\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003e0.0522\u003c/td\u003e\n      \u003ctd\u003e-0.0522\u003c/td\u003e\n      \u003ctd\u003e0.0152\u003c/td\u003e\n      \u003ctd\u003e-0.0266\u003c/td\u003e\n      \u003ctd\u003e0.0439\u003c/td\u003e\n      \u003ctd\u003e0.0391\u003c/td\u003e\n      \u003ctd\u003e-0.1045\u003c/td\u003e\n      \u003ctd\u003e0.0137\u003c/td\u003e\n      \u003ctd\u003e-0.2421\u003c/td\u003e\n      \u003ctd\u003e-0.0037\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0.0299\u003c/td\u003e\n      \u003ctd\u003e0.0538\u003c/td\u003e\n      \u003ctd\u003e0.0317\u003c/td\u003e\n      \u003ctd\u003e0.0173\u003c/td\u003e\n      \u003ctd\u003e0.0222\u003c/td\u003e\n      \u003ctd\u003e-0.0019\u003c/td\u003e\n      \u003ctd\u003e-0.0311\u003c/td\u003e\n      \u003ctd\u003e0.2421\u003c/td\u003e\n      \u003ctd\u003e0.1410\u003c/td\u003e\n      \u003ctd\u003e-0.0762\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e5 rows × 205 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\n# Map weights for the first principal component to corresponding feature names\n# and then print the linked values, sorted by weight.\n# HINT: Try defining a function here or in a new cell that you can reuse in the\n# other cells.\n# (ref at bottom of notebook, had to find some help on plotting this due to limited skill on this stuff)\n\ndef visualize_pca(data, pca, loc):\n    df = pd.DataFrame(np.round(pca.components_, 4), columns=data.keys()).iloc[loc - 1]\n    df.sort_values(ascending=False, inplace=True)\n    df = pd.concat([df.head(3), df.tail(3)])\n    df.plot(kind='bar', title='Component ' + str(loc))\n    p = plt.gca()\n    p.set_axisbelow(True)\n    \n    plt.show()\n\n```\n\n\n```python\nvisualize_pca(azdias, pca_100, 1)\n```\n\n\n    \n![png](output_92_0.png)\n    \n\n\n\n```python\nvisualize_pca(azdias, pca_100, 2)\n```\n\n\n    \n![png](output_93_0.png)\n    \n\n\n\n```python\nvisualize_pca(azdias, pca_100, 3)\n```\n\n\n    \n![png](output_94_0.png)\n    \n\n\n### Discussion 2.3: Interpret Principal Components\n\n(Double-click this cell and replace this text with your own text, reporting your observations from detailed investigation of the first few principal components generated. Can we interpret positive and negative values from them in a meaningful way?)\n\n### 1. Component 1\n\nTop Features:\n\n - `LP_STATUS_GROB`: `person`: `categorical`\n     - This feature refers to \"social status, rough scale\". This feature maps earner income from (1) low-income to (5) top earner.  This is a \"rougher\" more generic feature as compared to a similar feature `LP_STATUS_FEIN`, which is a more granular fine grained breakdown of social status.\n - `HH_EINKOMMEN_SCORE` \n     - This feature refers to estimated household income, ranging from (1) highest income to (6) very low income.\n - `CAMEO_INTL_2015_WEALTH`\n     - This feature is one of our added onehot encoded features.  The base feature is CAMEO_INTL_2015, which is \"Wealth / Life Stage Typology\".  This particular feature, WEALTH, refers to the economic status.  This ranges from (1) Wealthy Households to (5) Poorer Households\n     \n\nBottom Features:\n\n- `FINANZ_MINIMALIST` \n    - This feature refers to financial typlogy, particularly low financial interest\n    \n- `KBA05_ANTG1`\n    - This feature refers to \"Number of 1-2 family houses in microcell\"\n    \n- `MOBI_REGIO`\n    - This feature refers to \"Movement Patterns\".  With (1) being very high movement to (5) very low movement and (6) none.\n\n\u003e\u003e\u003e With this component we see a trend with wealth and economic status, with each feature having to do with money and wellbeing.\n     \n### 2. Component 2\n\nTop Features:\n\n- `ALTERSKATEGORIE_GROB`\n    - This feature refers to estimated age base on analysis.\n\n- `FINANZ_VORSORGER`\n    - This feature refers to financial typology.\n    \n- `ZABEOTYP`\n    - This feature refers to \"Energy Consumption\"  With (1) being unknwown, (2) being 'green' all the way to (6) 'indifferent' and (9) unknown.\n    \nBottom Features:\n\n- `SEMIO_REL`\n    -  This feature refers to Personality typology.  \n    \n- `FINANZ_SPARER`\n    - This feature refers to financial typology.  In this case we refer to \"money-save\".\n\n- `PRAEGENDE_JUGENDJAHRE_GENERATION`\n    - This feature is an encoded feature from the base `PRAEGENDE_JUGENDJAHRE`.  This refers to \"Dominating movement of person's youth (avantgarde, vs mainstream, east vs west).  In this particular feature we look to generation, specifically 40s, 50s, 60s, 70s, 80s and 90s.\n    \n    \n\nAs we review the first top components of our Principal Component Analysis, the driving features seem to be about economic status and wealth and income.  These seem to drive a lot of the conclusions around the data.  By reviewing the bottom features of the first two components we see some similiarly grouped data around finance, but in this case its about not caring to much about it.  Minimal interest in finance and \"money\" savers.  There is also some similar data in the realm of movement, where did you live, do you move much, etc.\n\n\n----\n\n\n```python\ndef plot_data(data, labels):\n    '''\n    Plot data with colors associated with labels\n    '''\n    fig = plt.figure();\n    ax = Axes3D(fig)\n    ax.scatter(data[:, 0], data[:, 1], data[:, 2], c=labels, cmap='tab10');\n```\n\n## Step 3: Clustering\n\n### Step 3.1: Apply Clustering to General Population\n\nYou've assessed and cleaned the demographics data, then scaled and transformed them. Now, it's time to see how the data clusters in the principal components space. In this substep, you will apply k-means clustering to the dataset and use the average within-cluster distances from each point to their assigned cluster's centroid to decide on a number of clusters to keep.\n\n- Use sklearn's [KMeans](http://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans) class to perform k-means clustering on the PCA-transformed data.\n- Then, compute the average difference from each point to its assigned cluster's center. **Hint**: The KMeans object's `.score()` method might be useful here, but note that in sklearn, scores tend to be defined so that larger is better. Try applying it to a small, toy dataset, or use an internet search to help your understanding.\n- Perform the above two steps for a number of different cluster counts. You can then see how the average distance decreases with an increasing number of clusters. However, each additional cluster provides a smaller net benefit. Use this fact to select a final number of clusters in which to group the data. **Warning**: because of the large size of the dataset, it can take a long time for the algorithm to resolve. The more clusters to fit, the longer the algorithm will take. You should test for cluster counts through at least 10 clusters to get the full picture, but you shouldn't need to test for a number of clusters above about 30.\n- Once you've selected a final number of clusters to use, re-fit a KMeans instance to perform the clustering operation. Make sure that you also obtain the cluster assignments for the general demographics data, since you'll be using them in the final Step 3.3.\n\n\n```python\n# Over a number of different cluster counts...\nscores = []\ncenters = list(range(1, 50))\nsample = X_pca_100[np.random.choice(X_pca_100.shape[0], int(X_pca_100.shape[0] * 0.20), replace=False)]\n\nfor center in centers:\n    # run k-means clustering on the data and...\n    kmeans = KMeans(n_clusters=center)\n    model = kmeans.fit(sample)\n    labels = model.predict(sample)\n    \n    \n    # compute the average within-cluster distances.\n    score = np.abs(model.score(sample))\n    scores.append(score)\n    \n```\n\n\n```python\nplt.plot(centers, scores)\n```\n\n\n\n\n    [\u003cmatplotlib.lines.Line2D at 0x1fc1cdab730\u003e]\n\n\n\n\n    \n![png](output_100_1.png)\n    \n\n\n\n```python\n# Refitting the dataset with our 30 clusters\n\nkmeans = KMeans(n_clusters=30)\nmodel = kmeans.fit(X_pca_100)\nlabels = model.predict(X_pca_100)\n```\n\n\n```python\nplot_data(X_pca_100, labels)\n```\n\n\n    \n![png](output_102_0.png)\n    \n\n\n### Discussion 3.1: Apply Clustering to General Population\n\n\nFor this task I reduced the dataset down to 33% or the original data, then later down to 20%.  I ran a genric loop from 1 to 50 and ran the KMeans algorithm on the data with the loop index indicating the number of clusters to use.  I then printed these all out and saved them to a list.  Upon review of the cluster scoring, I was happy with 30 clusters being good to use going forward.\n\n\n### Step 3.2: Apply All Steps to the Customer Data\n\nNow that you have clusters and cluster centers for the general population, it's time to see how the customer data maps on to those clusters. Take care to not confuse this for re-fitting all of the models to the customer data. Instead, you're going to use the fits from the general population to clean, transform, and cluster the customer data. In the last step of the project, you will interpret how the general population fits apply to the customer data.\n\n- Don't forget when loading in the customers data, that it is semicolon (`;`) delimited.\n- Apply the same feature wrangling, selection, and engineering steps to the customer demographics using the `clean_data()` function you created earlier. (You can assume that the customer demographics data has similar meaning behind missing data patterns as the general demographics data.)\n- Use the sklearn objects from the general demographics data, and apply their transformations to the customers data. That is, you should not be using a `.fit()` or `.fit_transform()` method to re-fit the old objects, nor should you be creating new sklearn objects! Carry the data through the feature scaling, PCA, and clustering steps, obtaining cluster assignments for all of the data in the customer demographics data.\n\n\n```python\n# Load in the customer demographics data.\ncustomers = pd.read_csv('Udacity_CUSTOMERS_Subset.csv', delimiter=';')\n```\n\n\n```python\nprint(customers.shape)\ncustomers.head()\n```\n\n    (191652, 85)\n    \n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eAGER_TYP\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eCJT_GESAMTTYP\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG1\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG2\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG3\u003c/th\u003e\n      \u003cth\u003ePLZ8_ANTG4\u003c/th\u003e\n      \u003cth\u003ePLZ8_BAUMAX\u003c/th\u003e\n      \u003cth\u003ePLZ8_HHZ\u003c/th\u003e\n      \u003cth\u003ePLZ8_GBZ\u003c/th\u003e\n      \u003cth\u003eARBEIT\u003c/th\u003e\n      \u003cth\u003eORTSGR_KLS9\u003c/th\u003e\n      \u003cth\u003eRELAT_AB\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e0.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003e-1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e6.0\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e5.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e5 rows × 85 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\ndef clean_attr2(x, name):\n    attr = feat_info[feat_info['attribute'] == name]\n    \n    # if the row DNE, return early\n    if len(attr) == 0:\n        return\n    \n    nan_indicators = attr.iloc[0].missing_or_unknown\n    return x.map(lambda z: np.nan if str(z) in nan_indicators else z) \n```\n\n\n```python\n# Apply preprocessing, feature transformation, and clustering from the general\n# demographics onto the customer data, obtaining cluster predictions for the\n# customer demographics data.\n\ncustomer_processed = clean_data2(customers.copy(deep=True))\n```\n\n\n```python\nprint(f'azdias cols: {len(azdias.columns)}.  Customer Cols: {len(customer_processed.columns)}')\n```\n\n    azdias cols: 206.  Customer Cols: 204\n    \n\n\n```python\n# Compare our two dataframes for difference\nlist(set(azdias.columns) - set(customer_processed.columns))\n```\n\n\n\n\n    ['GEBAEUDETYP_5.0', 'TITEL_KZ_2.0']\n\n\n\n\n```python\n# The customer data does not have values 5 for GEBAEUDETYP and 2 for TITEL_KZ.\n# These columns DNE since our one hot encoding would generate these based on values in the row.  \n# We need consistent datashape to proceed.\ncustomers_copy = customers.copy(deep=True)\ncustomers_copy['GEBAEUDETYP_5.0'] = 0\ncustomers_copy['TITEL_KZ_2.0'] = 0\n```\n\n\n```python\ncustomers_copy['TITEL_KZ_2.0'].value_counts()\n```\n\n\n\n\n    0    191652\n    Name: TITEL_KZ_2.0, dtype: int64\n\n\n\n\n```python\nprint(customers_copy.shape)\n\n# Rerun our new edited DF through our clean function\ncustomer_processed = clean_data2(customers_copy)\nprint(customer_processed.shape)\n```\n\n    (191652, 87)\n    (191652, 206)\n    \n\n\n```python\n#### Confirm data is same\nlist(set(customer_processed.columns) - set(azdias.columns))\n\n```\n\n\n\n\n    []\n\n\n\n\n```python\ncustomer_processed.head()\n```\n\n\n\n\n\u003cdiv\u003e\n\u003cstyle scoped\u003e\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n\u003c/style\u003e\n\u003ctable border=\"1\" class=\"dataframe\"\u003e\n  \u003cthead\u003e\n    \u003ctr style=\"text-align: right;\"\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003eALTERSKATEGORIE_GROB\u003c/th\u003e\n      \u003cth\u003eANREDE_KZ\u003c/th\u003e\n      \u003cth\u003eFINANZ_MINIMALIST\u003c/th\u003e\n      \u003cth\u003eFINANZ_SPARER\u003c/th\u003e\n      \u003cth\u003eFINANZ_VORSORGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_ANLEGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_UNAUFFAELLIGER\u003c/th\u003e\n      \u003cth\u003eFINANZ_HAUSBAUER\u003c/th\u003e\n      \u003cth\u003eGREEN_AVANTGARDE\u003c/th\u003e\n      \u003cth\u003eHEALTH_TYP\u003c/th\u003e\n      \u003cth\u003e...\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_8D\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9A\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9B\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9C\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9D\u003c/th\u003e\n      \u003cth\u003eCAMEO_DEU_2015_9E\u003c/th\u003e\n      \u003cth\u003ePRAEGENDE_JUGENDJAHRE_GENERATION\u003c/th\u003e\n      \u003cth\u003ePRAEGENDE_JUGENDJAHRE_MOVEMENT\u003c/th\u003e\n      \u003cth\u003eCAMEO_INTL_2015_WEALTH\u003c/th\u003e\n      \u003cth\u003eCAMEO_INTL_2015_LIFESTAGE\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003e0\u003c/th\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e1\u003c/th\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n      \u003ctd\u003eNaN\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e2\u003c/th\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e3\u003c/th\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003cth\u003e4\u003c/th\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e3\u003c/td\u003e\n      \u003ctd\u003e1\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e5\u003c/td\u003e\n      \u003ctd\u003e2\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e3.0\u003c/td\u003e\n      \u003ctd\u003e...\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e2.0\u003c/td\u003e\n      \u003ctd\u003e4.0\u003c/td\u003e\n      \u003ctd\u003e1.0\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e5 rows × 206 columns\u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\n```python\n# As found above, there are the same indexes on each dataframe\n\n# Note, originally we were dropping na, but we cant do that with the customer data set.\n# So I had to go back to the original fitting and adjust how we handled nan\n# customer_processed = customer_processed.dropna()\n\nimputer_data = imputer.transform(customer_processed)\n```\n\n\n```python\ncustomer_processed.shape\n```\n\n\n\n\n    (191652, 206)\n\n\n\n\n```python\nstandardized_data = scaler.fit_transform(imputer_data)\n```\n\n\n```python\nX_pca_customer = pca_100.transform(standardized_data)\n```\n\n\n```python\ncustomer_kmeans_labels = kmeans.predict(X_pca_customer)\n```\n\n### Step 3.3: Compare Customer Data to Demographics Data\n\nAt this point, you have clustered data based on demographics of the general population of Germany, and seen how the customer data for a mail-order sales company maps onto those demographic clusters. In this final substep, you will compare the two cluster distributions to see where the strongest customer base for the company is.\n\nConsider the proportion of persons in each cluster for the general population, and the proportions for the customers. If we think the company's customer base to be universal, then the cluster assignment proportions should be fairly similar between the two. If there are only particular segments of the population that are interested in the company's products, then we should see a mismatch from one to the other. If there is a higher proportion of persons in a cluster for the customer data compared to the general population (e.g. 5% of persons are assigned to a cluster for the general population, but 15% of the customer data is closest to that cluster's centroid) then that suggests the people in that cluster to be a target audience for the company. On the other hand, the proportion of the data in a cluster being larger in the general population than the customer data (e.g. only 2% of customers closest to a population centroid that captures 6% of the data) suggests that group of persons to be outside of the target demographics.\n\nTake a look at the following points in this step:\n\n- Compute the proportion of data points in each cluster for the general population and the customer data. Visualizations will be useful here: both for the individual dataset proportions, but also to visualize the ratios in cluster representation between groups. Seaborn's [`countplot()`](https://seaborn.pydata.org/generated/seaborn.countplot.html) or [`barplot()`](https://seaborn.pydata.org/generated/seaborn.barplot.html) function could be handy.\n  - Recall the analysis you performed in step 1.1.3 of the project, where you separated out certain data points from the dataset if they had more than a specified threshold of missing values. If you found that this group was qualitatively different from the main bulk of the data, you should treat this as an additional data cluster in this analysis. Make sure that you account for the number of data points in this subset, for both the general population and customer datasets, when making your computations!\n- Which cluster or clusters are overrepresented in the customer dataset compared to the general population? Select at least one such cluster and infer what kind of people might be represented by that cluster. Use the principal component interpretations from step 2.3 or look at additional components to help you make this inference. Alternatively, you can use the `.inverse_transform()` method of the PCA and StandardScaler objects to transform centroids back to the original data space and interpret the retrieved values directly.\n- Perform a similar investigation for the underrepresented clusters. Which cluster or clusters are underrepresented in the customer dataset compared to the general population, and what kinds of people are typified by these clusters?\n\n\n```python\n# Compare the proportion of data in each cluster for the customer data to the\n# proportion of data in each cluster for the general population.\n\nplt.figure(figsize=(15, 8))\nplt.subplots_adjust(hspace = 1, wspace=.3)\nplt.subplot(121)\n\nsns.countplot(customer_kmeans_labels)\n\nplt.title('Customers Data')\nplt.subplot(122)\nsns.countplot(labels)\n\nplt.title('General Pop Data')\nplt.show()\n```\n\n\n    \n![png](output_122_0.png)\n    \n\n\n\n```python\ncounts_customer = Counter(customer_kmeans_labels)\nn_customers = X_pca_customer.shape[0]\n\ncustomer_freqs = {label: 100*(freq / n_customers) for label, freq in counts_customer.items()}\nplt.figure(figsize = (10, 5));\nplt.bar(customer_freqs.keys(), customer_freqs.values());\nplt.title('Customer Cluster Frequencies', fontsize = 18);\nplt.xlabel('Cluster Label');\nplt.ylabel('Percent of Customers');\n```\n\n\n    \n![png](output_123_0.png)\n    \n\n\n\n```python\n# What kinds of people are part of a cluster that is overrepresented in the\n# customer data compared to the general population?\n\ncentroid = scaler.inverse_transform(pca_100.inverse_transform(model.cluster_centers_[17]))\nb = pd.Series(centroid, index=customer_processed.columns)\nb.head(10)\n```\n\n\n\n\n    ALTERSKATEGORIE_GROB     2.093397\n    ANREDE_KZ                1.814761\n    FINANZ_MINIMALIST        2.916143\n    FINANZ_SPARER            3.385651\n    FINANZ_VORSORGER         3.292351\n    FINANZ_ANLEGER           4.347848\n    FINANZ_UNAUFFAELLIGER    4.199011\n    FINANZ_HAUSBAUER         3.130262\n    GREEN_AVANTGARDE         0.180336\n    HEALTH_TYP               1.982927\n    dtype: float64\n\n\n\n\n```python\n# What kinds of people are part of a cluster that is underrepresented in the\n# customer data compared to the general population?\n\ncentroid = scaler.inverse_transform(pca_100.inverse_transform(model.cluster_centers_[1]))\nb = pd.Series(centroid, index=customer_processed.columns)\nb.head(10)\n```\n\n\n\n\n    ALTERSKATEGORIE_GROB     3.711531\n    ANREDE_KZ                1.597270\n    FINANZ_MINIMALIST        3.902063\n    FINANZ_SPARER            1.289114\n    FINANZ_VORSORGER         4.740248\n    FINANZ_ANLEGER           2.489613\n    FINANZ_UNAUFFAELLIGER    1.543146\n    FINANZ_HAUSBAUER         3.482416\n    GREEN_AVANTGARDE         0.149575\n    HEALTH_TYP               1.873302\n    dtype: float64\n\n\n\n### Discussion 3.3: Compare Customer Data to Demographics Data\n\n\nFor our final analysis of the customer data to demographic data, I used clusters 17 as one that was overrepresented and 1 as a cluster that was underrepresented.  In cluster 17, ALTERSKATEGORIE_GROB has a value of 2.09 compared to that of cluster 1 which has a value of 3.71.  ALTERSKATEGORIE_GROB representes estimated age.  Using this information we can theorize that cluster 17 contains a younger population.  Cluster 17, according to FINANZ_MINIMALIST (financial typology), has a value of 2.9 compared to 3.9 which leads us to concur that cluster 17 has more population with high degree of minimalist living.  Cluster 1 tends to point towards a more average/low degree of minimalism.  Looking at a another feature, FINANZ_UNAUFFAELLIGER (Less conspicuous finance), cluster 1","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreyjs%2Fidentify_customer_segments","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoreyjs%2Fidentify_customer_segments","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoreyjs%2Fidentify_customer_segments/lists"}