<jupyter_start><jupyter_text>Lambda School Data Science, Unit 2: Predictive Modeling Applied Modeling, Module 3You will use your portfolio project dataset for all assignments this sprint. AssignmentComplete these tasks for your project, and document your work.- [ ] Continue to iterate on your project: data cleaning, exploration, feature engineering, modeling.- [ ] Make at least 1 partial dependence plot to explain your model.- [ ] Share at least 1 visualization on Slack.(If you have not yet completed an initial model yet for your portfolio project, then do today's assignment using your Tanzania Waterpumps model.) Stretch Goals- [ ] Make multiple PDPs with 1 feature in isolation.- [ ] Make multiple PDPs with 2 features in interaction.- [ ] If you log-transformed your regression target, then convert your PDP back to original units. - [ ] Use Plotly to make a 3D PDP.- [ ] Make PDPs with categorical feature(s). Use Ordinal Encoder, outside of a pipeline, to encode your data first. If there is a natural ordering, then take the time to encode it that way, instead of random integers. Then use the encoded data with pdpbox.I Get readable category names on your plot, instead of integer category codes. Links- [<NAME>: Interpretable Machine Learning — Partial Dependence Plots](https://christophm.github.io/interpretable-ml-book/pdp.html) + [animated explanation](https://twitter.com/ChristophMolnar/status/1066398522608635904)- [Kaggle / <NAME>: Machine Learning Explainability — Partial Dependence Plots](https://www.kaggle.com/dansbecker/partial-plots)- [Plotly: 3D PDP example](https://plot.ly/scikit-learn/plot-partial-dependence/partial-dependence-of-house-value-on-median-age-and-average-occupancy)<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly_express as px
import seaborn as sns
df = pd.read_csv('CA_Hosp_Mortality.csv', encoding = "ISO-8859-1")

pd.set_option('display.float_format', lambda x: '%.3f' % x)
# Cleaning function

def wrangle(X):
    
    X = X.copy()
    
    X = X.drop(columns='OSHPDID')
    # Change column names to more appropriate names without caps
    X = X.rename(columns={'YEAR':'Year', 'COUNTY':'County', 'HOSPITAL':'Hospital',
                        'Procedure/Condition':'Procedure_Condition',
                        'Risk Adjuested Mortality Rate':'RAMR', '# of Deaths':'Number_Deaths',
                        '# of Cases':'Number_Cases', 'Hospital Ratings':'Hospital_Ratings',
                        'LONGITUDE':'Longitude', 'LATITUDE':'Latitude'
                       })  
    
    # Remove rows where the value is for the entire state
    X = X.query("County != 'AAAA'") # AAAA is county code for State

    # Remove procedures that are not in every year and hidden NaN values
    X.replace({'AAA Repair':np.nan, 'AAA Repair Unruptured':np.nan, '.':np.nan}, inplace=True)
    X.dropna(inplace=True)
    
    # Change numeric columns from string to float
    numerics = ['RAMR', 'Number_Deaths', 'Number_Cases']
    for column in numerics:
        X[column] = X[column].astype(float)
    
    # Creating numeric values for hospital rating since it is in least to best
    X['Hospital_Ratings'].replace({'Worse':1, 'As Expected':2, 'Better':3}, inplace=True)
    
    return X

newdf = wrangle(df)
target = 'Number_Deaths'
features = newdf.columns.drop('Number_Deaths').tolist()

train = newdf.query('Year < 2014')
val = newdf.query('Year == 2014')
test = newdf.query('Year == 2015')

X_train = train[features]
y_train = train[target]

X_val = val[features]
y_val = val[target]

X_test = test[features]
y_test = test[target]

X_train.shape, y_train.shape, X_val.shape, y_val.shape, X_test.shape, y_test.shape
# XGBoost
# Tested XGBoost with numerical features only and with OrdinalEncoding of categoricals
# Numeric only: R^2 0.85, encoding: R^2 0.87
from sklearn.metrics import r2_score
from xgboost import XGBRegressor
from sklearn.pipeline import make_pipeline
import category_encoders as ce

gb = make_pipeline(
    ce.OrdinalEncoder(),
    XGBRegressor(n_estimators=200, objective='reg:squarederror', n_jobs=-1)
    )

# Only used when testing out no encoding
# X_train_numeric = X_train.select_dtypes(include='number')
# X_val_numeric = X_val.select_dtypes(include='number')

gb.fit(X_train, y_train)
y_pred = gb.predict(X_val)
print('Gradient Boosting R^2:', r2_score(y_val, y_pred))
# RandomizedSearchCV to find best hyperparams for the XGBoost
from scipy.stats import randint, uniform
from sklearn.model_selection import RandomizedSearchCV
gb_early = make_pipeline(
            ce.OrdinalEncoder(),
            XGBRegressor(objective='reg:squarederror', random_state=42)
)

param_distributions = {
    'xgbregressor__n_estimators': randint(100,1000),
    'xgbregressor__max_depth':randint(3, 10),
    'xgbregressor__learningrate': [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3]
}

search = RandomizedSearchCV(
    gb_early,
    param_distributions,
    n_iter=5,
    cv=2,
    scoring='neg_mean_absolute_error',
    verbose=10,
    return_train_score=True,
    n_jobs=-1
)

search.fit(X_train, y_train);
# Repeat XGBoost with best hyper params

gb = make_pipeline(
    ce.OrdinalEncoder(),
    XGBRegressor(n_estimators=300, objective='reg:squarederror',n_jobs=-1, learningrate=0.1, max_depth=7)
    )

gb.fit(X_train, y_train)
y_pred = gb.predict(X_val)
print('Gradient Boosting R^2:', r2_score(y_val, y_pred))
# Partial Dependence Plot - Hospital Rating

import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 72

from pdpbox.pdp import pdp_isolate, pdp_plot

feature = 'Hospital_Ratings'

isolated = pdp_isolate(
    model = gb,
    dataset=X_val,
    model_features=X_val.columns,
    feature=feature
)

pdp_plot(isolated, feature_name=feature, plot_lines=True, frac_to_plot=100)
plt.ylabel('Number of Deaths')
plt.ylim(-6, 5);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10836599079911399, 'fraction_numerical': 0.019424092690407225, 'mean_word_length': 4.302619692863595, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '548467', 'license': 'MIT', 'n_tokens_mistral': 2036, 'n_tokens_neox': 1880, 'n_words': 537, 'path': 'module3/assignment_applied_modeling_3.ipynb', 'repo_name': 'JohnMorrisonn/DS-Unit-2-Applied-Modeling-1', 'size': '5883'}