# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Days 9 Class Exercises: Seaborn

# For these class exercises, we will be using a wine quality dataset which was obtained from this URL:
# http://mlr.cs.umass.edu/ml/machine-learning-databases/wine-quality. The data for these exercises can be found in the `data` directory of this repository.
#
# <span style="float:right; margin-left:10px; clear:both;">![Task](../media/new_knowledge.png)</span> Additionally, with these class exercises we learn a few new things.  When new knowledge is introduced you'll see the icon shown on the right: 
#

# ## Get Started
# Import the Numpy, Pandas, Matplotlib (matplotlib magic) and Seaborn. 

# +
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# %matplotlib inline
# -

# ## Exercise 1. Explore the data
# First, read about this dataset from the file [../data/winequality.names](../data/winequality.names)

# Next, read in the file named `winequality-red.csv`. This data, despite the `csv` suffix, is separated using a semicolon.

wine = pd.read_csv("..//data/winequality-red.csv", sep=';')
wine.head()

# How many samples (observations) do we have?

wine.shape

# Are the data types for the columns in the dataframe appropriate for the type of data in each column?

wine.dtypes

# Any missing values?

wine.isna().sum()

wine.duplicated().sum()

# ## Exercise 2: Explore the Data

# The quality column contains our expected outcome. Wines scored as 0 are considered very bad and wines scored as 10 are very excellent.  Plot a bargraph to see how many samples are there per each quality of wine.  
#
# **Hints**: 
# - Use the [pd.Series.value_counts()](https://pandas.pydata.org/docs/reference/api/pandas.Series.value_counts.html) function to count the number of values
# - Panda DataFrames and Series have built in plotting funcitons  that use MatplotLib. Therefore, we can use the [pd.Series.plot.bar()](https://pandas.pydata.org/docs/reference/api/pandas.Series.plot.bar.html) function to simplify use of matplotlib.

wine['quality'].value_counts(sort = False).plot.bar();

# Now use Matplotlib functionality to recreate the plot (no need to color each bar)

qcounts =wine['quality'].value_counts(sort = False)
fig = plt.figure()

# Recreate the bargraph using Seaborn

sns.barplot(x = 'quality', data = wine )

# Describe the data for all of the columns in the dataframe. This includes our physicochemical measurements (independent data) as well as the quality data (dependent).



# Visualizing the data can sometimes better help undrestand it's limits. Create a single figure, that contains boxplots for each of the data columns. Use the [seaborn.boxplot()](https://seaborn.pydata.org/generated/seaborn.boxplot.html) function to do this:



#
# <span style="float:right; margin-left:10px; clear:both;">![Task](../media/new_knowledge.png)</span>In our plot, the axis labels are squished together and many of the box plots are too hard to see because all of them share the same y-axis coordinate system.  Unfortunately, not all Seaborn functions provide arguments to control the height and widht of a plot, the `boxplot` function is one of them.  However, remember that Seaborn uses matplotlib!  So, we can use matplot lib functions set the height using a command such as:
#
# ```python
# plt.figure(figsize=(10, 6))
# ```
# Where the first number is the width and the second number is the height.  Repeat the plot from the previous cell but add this line of code just above the figure.



# <span style="float:right; margin-left:10px; clear:both;">![Task](../media/new_knowledge.png)</span> Unfortunately, we are still unable to read some of the x-axis labels. But we can use Matplotlib to correct this.  When calling a Seaborn plot function it will return the Matplotlib axis object. We can then call functions on the axis such as the [set_xticklabels](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xticklabels.html) function. That function will allow us to set a rotation on the axis tick labels and it takes a `rotation` argument. For example. The following function call on an axis object named `g` will reset the tick labels (using the `get_xticklabels()` function) and set a rotation of 45 degrees.
#
# ```python
# g.set_xticklabels(g.get_xticklabels(), rotation=45);
# ```
#
# Try it on the wine data boxplot:



# The boxplots from some of the measurements are too squished to view their distribution.  The [seaborn.FacetGrid()](https://seaborn.pydata.org/generated/seaborn.FacetGrid.html) function can help. It allows us to divide our data into differnet panels of the same figure. But, it requires that our data be in tidy format.  

# <span style="float:right; margin-left:10px; clear:both;">![Task](../media/new_knowledge.png)</span>Using `FacetGrid` we can divide up our plots into rows and columns using variable.  Here are few important arguments that can be passed to the `FacetGrid` function.
#
# - **data**: Tidy (“long-form”) dataframe where each column is a variable and each row is an observation.
# - **row**, **col**: Variables that define subsets of the data, which will be drawn on separate facets in the grid.
# - **col_wrap**: “Wrap” the column variable at this width, so that the column facets span multiple rows. Incompatible with a row facet.
# - **sharex**, **sharey**: If true, the facets will share y axes across columns and/or x axes across rows.
#
# We have two variables in our tidy wine data set: "quality" and the "measurement".  We want to create a separate boxplot for each measurement regardless of quality in this case we can either have a grid of 1 column or 1 row. It is your choice.
#
# After you've created a `FacetGrid` you must then tell the grid what type of plot you want to draw. This is performed using the [map](https://seaborn.pydata.org/generated/seaborn.FacetGrid.map.html#seaborn.FacetGrid.map) function of the `seaborn.axisgrid.FacetGrid` object. Let's walk through a demonstration to see  how it works.
#
# First, import the tips dataset:
#
# ```python
# tips = sns.load_dataset('tips')
# tips.head()
# ```



# Next create a `FacetGrid` that will divide the data by meal time and sex
#
# ```python
# g = sns.FacetGrid(tips, col="time", row="sex")
# ```



# Notice the result is an empty grid.  Now we need to indicate the type of plot we weant to draw. For this example, we'll draw a `sns.scatterplot` plot.  When we call the `map` function any arguments given get passed to the scatterplot function:
#
# ```python
# g = sns.FacetGrid(tips, col="time", row="sex")
# g.map(sns.scatterplot, "total_bill", "tip");
# ```



# Now, lets use a `FacetGrid` to create boxplots for each measurement in separate facet. Do the following
# 1. Tidy the wine data. Be sure to keep the `quality` column as is, and melt the others into a single column named `measurement`
# 2. Unlike the tip data, we only have one variable we want to calculate boxplots for: measurement. We don't not want to create box plots for measurement and quality. So, we only need one row of plots.  
# 3. Make the row of plots span 2 rows so we can see them more easily.
# 4. Make sure that each boxplot does not share the x-axis coordinates with all other boxplots.





# Redo the FacetGrid plot but use the [seaborn.violinplot](https://seaborn.pydata.org/generated/seaborn.violinplot.html) instead.
#



# Redo the FacetGrid plot but with the [seaborn.swarmplot](https://seaborn.pydata.org/generated/seaborn.swarmplot.html) instead. Be sure to set the `size` argument for the swarmplot to 1. 
#
# **Note**: this may take awhile to create.



# Next, let's look for columns that might show correlation with other columns. Colinear data can be problematic for some analyses. Use the Seaborn [seaborn.pairplot](https://seaborn.pydata.org/generated/seaborn.pairplot.html) function to do this.  
#
# Be sure to:
#
# - Color each point with the quality value.
# - Use the 'tab10' palette for coloring
#
# **Note**: this may take awhile to create)



# Do you see any measurement types  that are correlated?

# Perform correlation analysis on the data columns. Exclude the `quality` column from the correlation analysis. 



# Use the [seaborn.heatmap](https://seaborn.pydata.org/generated/seaborn.heatmap.html) function to create a heatmap of the correlation values between data columns. 
#
# Be sure to:
# - Make sure the color values span from -1 to 1 (i.e., they are not inferred from the data).
# - Show the correlation values in the cells of the heatmap
# - Make the figure large enough to read the correlation values
# - Make the cells of the heatmap square



StarcoderdataJupyterScriptsDedupFiltered