<jupyter_start><jupyter_text>0.0. IMPORTS<jupyter_code>import math
import numpy  as np
import pandas as pd
import inflection
import seaborn as sns


from scipy                 import stats  as ss
from matplotlib            import pyplot as plt
from IPython.display       import Image
from IPython.core.display  import HTML<jupyter_output><empty_output><jupyter_text>0.1. Helper Functions<jupyter_code>def cramer_v( x, y ):
    cm = pd.crosstab( x, y ).to_numpy()
    n = cm.sum()
    r, k = cm.shape
    
    chi2 = ss.chi2_contingency( cm )[0]
    chi2corr = max( 0, chi2 - (k-1)*(r-1)/(n-1) )
    
    kcorr = k - (k-1)**2/(n-1)
    rcorr = r - (r-1)**2/(n-1)
    
    return np.sqrt( (chi2corr/n) / ( min( kcorr-1, rcorr-1 ) ) )



def jupyter_settings():
    %matplotlib inline
    %pylab inline
    
    plt.style.use( 'bmh' )
    plt.rcParams['figure.figsize'] = [25, 12]
    plt.rcParams['font.size'] = 24
    
    display( HTML( '<style>.container { width:100% !important; }</style>') )
    pd.options.display.max_columns = None
    pd.options.display.max_rows = None
    pd.set_option( 'display.expand_frame_repr', False )
    
    sns.set()
jupyter_settings()<jupyter_output><empty_output><jupyter_text>0.2. Loading data<jupyter_code>df_sales_raw = pd.read_csv( '../input/datasetsprod/Data/train.csv', low_memory=False )
df_store_raw = pd.read_csv( '../input/datasetsprod/Data/store.csv', low_memory=False )

# merge
df_raw = pd.merge( df_sales_raw, df_store_raw, how='left', on='Store' )<jupyter_output><empty_output><jupyter_text>1.0. PASSO 01 - DESCRICAO DOS DADOS<jupyter_code>df1 = df_raw.copy()<jupyter_output><empty_output><jupyter_text>1.1. Rename Columns<jupyter_code>cols_old = ['Store', 'DayOfWeek', 'Date', 'Sales', 'Customers', 'Open', 'Promo', 'StateHoliday', 'SchoolHoliday', 
            'StoreType', 'Assortment', 'CompetitionDistance', 'CompetitionOpenSinceMonth',
            'CompetitionOpenSinceYear', 'Promo2', 'Promo2SinceWeek', 'Promo2SinceYear', 'PromoInterval']

snakecase = lambda x: inflection.underscore( x )

cols_new = list( map( snakecase, cols_old ) )

# rename
df1.columns = cols_new<jupyter_output><empty_output><jupyter_text>1.2. Data Dimensions<jupyter_code>print( 'Number of Rows: {}'.format( df1.shape[0] ) )
print( 'Number of Cols: {}'.format( df1.shape[1] ) )<jupyter_output><empty_output><jupyter_text>1.3. Data Types<jupyter_code>df1['date'] = pd.to_datetime( df1['date'] )
df1.dtypes<jupyter_output><empty_output><jupyter_text>1.4. Check NA<jupyter_code>df1.isna().sum()<jupyter_output><empty_output><jupyter_text>1.5. Fillout NA<jupyter_code>df1.sample()
#competition_distance        
df1['competition_distance'] = df1['competition_distance'].apply( lambda x: 200000.0 if math.isnan( x ) else x )

#competition_open_since_month
df1['competition_open_since_month'] = df1.apply( lambda x: x['date'].month if math.isnan( x['competition_open_since_month'] ) else x['competition_open_since_month'], axis=1 )

#competition_open_since_year 
df1['competition_open_since_year'] = df1.apply( lambda x: x['date'].year if math.isnan( x['competition_open_since_year'] ) else x['competition_open_since_year'], axis=1 )

#promo2_since_week           
df1['promo2_since_week'] = df1.apply( lambda x: x['date'].week if math.isnan( x['promo2_since_week'] ) else x['promo2_since_week'], axis=1 )

#promo2_since_year           
df1['promo2_since_year'] = df1.apply( lambda x: x['date'].year if math.isnan( x['promo2_since_year'] ) else x['promo2_since_year'], axis=1 )

#promo_interval              
month_map = {1: 'Jan',  2: 'Fev',  3: 'Mar',  4: 'Apr',  5: 'May',  6: 'Jun',  7: 'Jul',  8: 'Aug',  9: 'Sep',  10: 'Oct', 11: 'Nov', 12: 'Dec'}

df1['promo_interval'].fillna(0, inplace=True )

df1['month_map'] = df1['date'].dt.month.map( month_map )

df1['is_promo'] = df1[['promo_interval', 'month_map']].apply( lambda x: 0 if x['promo_interval'] == 0 else 1 if x['month_map'] in x['promo_interval'].split( ',' ) else 0, axis=1 )

df1.isna().sum()<jupyter_output><empty_output><jupyter_text>1.6. Change Data Types<jupyter_code># competiton
df1['competition_open_since_month'] = df1['competition_open_since_month'].astype( int )
df1['competition_open_since_year'] = df1['competition_open_since_year'].astype( int )
    
# promo2
df1['promo2_since_week'] = df1['promo2_since_week'].astype( int )
df1['promo2_since_year'] = df1['promo2_since_year'].astype( int )<jupyter_output><empty_output><jupyter_text>1.7. Descriptive Statistics<jupyter_code>num_attributes = df1.select_dtypes( include=['int64', 'float64'] )
cat_attributes = df1.select_dtypes( exclude=['int64', 'float64', 'datetime64[ns]'] )<jupyter_output><empty_output><jupyter_text>1.7.1. Numerical Atributes<jupyter_code># Central Tendency - mean, meadina 
ct1 = pd.DataFrame( num_attributes.apply( np.mean ) ).T
ct2 = pd.DataFrame( num_attributes.apply( np.median ) ).T

# dispersion - std, min, max, range, skew, kurtosis
d1 = pd.DataFrame( num_attributes.apply( np.std ) ).T 
d2 = pd.DataFrame( num_attributes.apply( min ) ).T 
d3 = pd.DataFrame( num_attributes.apply( max ) ).T 
d4 = pd.DataFrame( num_attributes.apply( lambda x: x.max() - x.min() ) ).T 
d5 = pd.DataFrame( num_attributes.apply( lambda x: x.skew() ) ).T 
d6 = pd.DataFrame( num_attributes.apply( lambda x: x.kurtosis() ) ).T 

# concatenar
m = pd.concat( [d2, d3, d4, ct1, ct2, d1, d5, d6] ).T.reset_index()
m.columns = ['attributes', 'min', 'max', 'range', 'mean', 'median', 'std', 'skew', 'kurtosis']
m
sns.distplot( df1['competition_distance'], kde=False )<jupyter_output><empty_output><jupyter_text>1.7.2. Categorical Atributes<jupyter_code>cat_attributes.apply( lambda x: x.unique().shape[0] )
aux = df1[(df1['state_holiday'] != '0') & (df1['sales'] > 0)]

plt.subplot( 1, 3, 1 )
sns.boxplot( x='state_holiday', y='sales', data=aux )

plt.subplot( 1, 3, 2 )
sns.boxplot( x='store_type', y='sales', data=aux )

plt.subplot( 1, 3, 3 )
sns.boxplot( x='assortment', y='sales', data=aux )<jupyter_output><empty_output><jupyter_text>2.0. PASSO 02 - FEATURE ENGINEERING<jupyter_code>df2 = df1.copy()<jupyter_output><empty_output><jupyter_text>2.1. Mapa Mental de Hipoteses<jupyter_code>Image( 'img/MindMapHypothesis.png' )<jupyter_output><empty_output><jupyter_text>2.2. Criacao das Hipoteses  2.2.1. Hipoteses Loja **1.** Lojas com número maior de funcionários deveriam vender mais.**2.** Lojas com maior capacidade de estoque deveriam vender mais.**3.** Lojas com maior porte deveriam vender mais.**4.** Lojas com maior sortimentos deveriam vender mais.**5.** Lojas com competidores mais próximos deveriam vender menos.**6.** Lojas com competidores à mais tempo deveriam vendem mais.  2.2.2. Hipoteses Produto **1.** Lojas que investem mais em Marketing deveriam vender mais.**2.** Lojas com maior exposição de produto deveriam vender mais.**3.** Lojas com produtos com preço menor deveriam vender mais.**5.** Lojas com promoções mais agressivas ( descontos maiores ), deveriam vender mais.**6.** Lojas com promoções ativas por mais tempo deveriam vender mais.**7.** Lojas com mais dias de promoção deveriam vender mais.**8.** Lojas com mais promoções consecutivas deveriam vender mais.  2.2.3. Hipoteses Tempo **1.** Lojas abertas durante o feriado de Natal deveriam vender mais.**2.** Lojas deveriam vender mais ao longo dos anos.**3.** Lojas deveriam vender mais no segundo semestre do ano.**4.** Lojas deveriam vender mais depois do dia 10 de cada mês.**5.** Lojas deveriam vender menos aos finais de semana.**6.** Lojas deveriam vender menos durante os feriados escolares.  2.3. Lista Final de Hipóteses **1.** Lojas com maior sortimentos deveriam vender mais.**2.** Lojas com competidores mais próximos deveriam vender menos.**3.** Lojas com competidores à mais tempo deveriam vendem mais. **4.** Lojas com promoções ativas por mais tempo deveriam vender mais.**5.** Lojas com mais dias de promoção deveriam vender mais.**7.** Lojas com mais promoções consecutivas deveriam vender mais. **8.** Lojas abertas durante o feriado de Natal deveriam vender mais.**9.** Lojas deveriam vender mais ao longo dos anos.**10.** Lojas deveriam vender mais no segundo semestre do ano.**11.** Lojas deveriam vender mais depois do dia 10 de cada mês.**12.** Lojas deveriam vender menos aos finais de semana.**13.** Lojas deveriam vender menos durante os feriados escolares.  2.4. Feature Engineering<jupyter_code># year
df2['year'] = df2['date'].dt.year

# month
df2['month'] = df2['date'].dt.month

# day
df2['day'] = df2['date'].dt.day

# week of year
df2['week_of_year'] = df2['date'].dt.weekofyear

# year week
df2['year_week'] = df2['date'].dt.strftime( '%Y-%W' )

# competition since
df2['competition_since'] = df2.apply( lambda x: datetime.datetime( year=x['competition_open_since_year'], month=x['competition_open_since_month'],day=1 ), axis=1 )
df2['competition_time_month'] = ( ( df2['date'] - df2['competition_since'] )/30 ).apply( lambda x: x.days ).astype( int )

# promo since
df2['promo_since'] = df2['promo2_since_year'].astype( str ) + '-' + df2['promo2_since_week'].astype( str )
df2['promo_since'] = df2['promo_since'].apply( lambda x: datetime.datetime.strptime( x + '-1', '%Y-%W-%w' ) - datetime.timedelta( days=7 ) )
df2['promo_time_week'] = ( ( df2['date'] - df2['promo_since'] )/7 ).apply( lambda x: x.days ).astype( int )

# assortment
df2['assortment'] = df2['assortment'].apply( lambda x: 'basic' if x == 'a' else 'extra' if x == 'b' else 'extended' )

# state holiday
df2['state_holiday'] = df2['state_holiday'].apply( lambda x: 'public_holiday' if x == 'a' else 'easter_holiday' if x == 'b' else 'christmas' if x == 'c' else 'regular_day' )<jupyter_output><empty_output><jupyter_text>3.0. PASSO 03 - FILTRAGEM DE VARIÁVEIS<jupyter_code>df3 = df2.copy()<jupyter_output><empty_output><jupyter_text>3.1. Filtragem das Linhas<jupyter_code>df3 = df3[(df3['open'] != 0) & (df3['sales'] > 0)]<jupyter_output><empty_output><jupyter_text>3.2. Selecao das Colunas<jupyter_code>cols_drop = ['customers', 'open', 'promo_interval', 'month_map']
df3 = df3.drop( cols_drop, axis=1 )<jupyter_output><empty_output><jupyter_text>4.0. PASSO 04 - ANALISE EXPLORATORIA DOS DADOS<jupyter_code>df4 = df3.copy()<jupyter_output><empty_output><jupyter_text>4.1. Analise Univariada  4.1.1. Response Variable<jupyter_code>sns.distplot( df4['sales'], kde=False  )<jupyter_output><empty_output><jupyter_text>4.1.2. Numerical Variable<jupyter_code>num_attributes.hist( bins=25 );<jupyter_output><empty_output><jupyter_text>4.1.3. Categorical Variable<jupyter_code># state_holiday
plt.subplot( 3, 2, 1 )
a = df4[df4['state_holiday'] != 'regular_day']
sns.countplot( a['state_holiday'] )

plt.subplot( 3, 2, 2 )
sns.kdeplot( df4[df4['state_holiday'] == 'public_holiday']['sales'], label='public_holiday', shade=True )
sns.kdeplot( df4[df4['state_holiday'] == 'easter_holiday']['sales'], label='easter_holiday', shade=True )
sns.kdeplot( df4[df4['state_holiday'] == 'christmas']['sales'], label='christmas', shade=True )

# store_type
plt.subplot( 3, 2, 3 )
sns.countplot( df4['store_type'] )

plt.subplot( 3, 2, 4 )
sns.kdeplot( df4[df4['store_type'] == 'a']['sales'], label='a', shade=True )
sns.kdeplot( df4[df4['store_type'] == 'b']['sales'], label='b', shade=True )
sns.kdeplot( df4[df4['store_type'] == 'c']['sales'], label='c', shade=True )
sns.kdeplot( df4[df4['store_type'] == 'd']['sales'], label='d', shade=True )

# assortment
plt.subplot( 3, 2, 5 )
sns.countplot( df4['assortment'] )

plt.subplot( 3, 2, 6 )
sns.kdeplot( df4[df4['assortment'] == 'extended']['sales'], label='extended', shade=True )
sns.kdeplot( df4[df4['assortment'] == 'basic']['sales'], label='basic', shade=True )
sns.kdeplot( df4[df4['assortment'] == 'extra']['sales'], label='extra', shade=True )<jupyter_output><empty_output><jupyter_text>4.2. Analise Bivariada  **H1.** Lojas com maior sortimentos deveriam vender mais.**FALSA** Lojas com MAIOR SORTIMENTO vendem MENOS.<jupyter_code>aux1 = df4[['assortment', 'sales']].groupby( 'assortment' ).sum().reset_index()
sns.barplot( x='assortment', y='sales', data=aux1 );

aux2 = df4[['year_week', 'assortment', 'sales']].groupby( ['year_week','assortment'] ).sum().reset_index()
aux2.pivot( index='year_week', columns='assortment', values='sales' ).plot()

aux3 = aux2[aux2['assortment'] == 'extra']
aux3.pivot( index='year_week', columns='assortment', values='sales' ).plot()<jupyter_output><empty_output><jupyter_text>**H2.** Lojas com competidores mais próximos deveriam vender menos.**FALSA** Lojas com COMPETIDORES MAIS PROXIMOS vendem MAIS.<jupyter_code>aux1 = df4[['competition_distance', 'sales']].groupby( 'competition_distance' ).sum().reset_index()

plt.subplot( 1, 3, 1 )
sns.scatterplot( x ='competition_distance', y='sales', data=aux1 );

plt.subplot( 1, 3, 2 )
bins = list( np.arange( 0, 20000, 1000) )
aux1['competition_distance_binned'] = pd.cut( aux1['competition_distance'], bins=bins )
aux2 = aux1[['competition_distance_binned', 'sales']].groupby( 'competition_distance_binned' ).sum().reset_index()
sns.barplot( x='competition_distance_binned', y='sales', data=aux2 );
plt.xticks( rotation=90 );

plt.subplot( 1, 3, 3 )
x = sns.heatmap( aux1.corr( method='pearson' ), annot=True );
bottom, top = x.get_ylim()
x.set_ylim( bottom+0.5, top-0.5 );<jupyter_output><empty_output><jupyter_text>**H3.** Lojas com competidores à mais tempo deveriam vendem mais.**FALSE** Lojas com COMPETIDORES À MAIS TEMPO vendem MENOS.<jupyter_code>plt.subplot( 1, 3, 1 )
aux1 = df4[['competition_time_month', 'sales']].groupby( 'competition_time_month' ).sum().reset_index()
aux2 = aux1[( aux1['competition_time_month'] < 120 ) & ( aux1['competition_time_month'] != 0 )]
sns.barplot( x='competition_time_month', y='sales', data=aux2 );
plt.xticks( rotation=90 );

plt.subplot( 1, 3, 2 )
sns.regplot( x='competition_time_month', y='sales', data=aux2 );

plt.subplot( 1, 3, 3 )
x = sns.heatmap( aux1.corr( method='pearson'), annot=True );
bottom, top = x.get_ylim()
x.set_ylim( bottom+0.5, top-0.5);<jupyter_output><empty_output><jupyter_text>**H4.** Lojas com promoções ativas por mais tempo deveriam vender mais.**FALSA** Lojas com promocoes ativas por mais tempo vendem menos, depois de um certo periodo de promocao<jupyter_code>aux1 = df4[['promo_time_week', 'sales']].groupby( 'promo_time_week').sum().reset_index()

grid = GridSpec( 2, 3 )

plt.subplot( grid[0,0] )
aux2 = aux1[aux1['promo_time_week'] > 0] # promo extendido
sns.barplot( x='promo_time_week', y='sales', data=aux2 );
plt.xticks( rotation=90 );

plt.subplot( grid[0,1] )
sns.regplot( x='promo_time_week', y='sales', data=aux2 );

plt.subplot( grid[1,0] )
aux3 = aux1[aux1['promo_time_week'] < 0] # promo regular
sns.barplot( x='promo_time_week', y='sales', data=aux3 );
plt.xticks( rotation=90 );

plt.subplot( grid[1,1] )
sns.regplot( x='promo_time_week', y='sales', data=aux3 );

plt.subplot( grid[:,2] )
sns.heatmap( aux1.corr( method='pearson' ), annot=True );<jupyter_output><empty_output><jupyter_text>**H5.** Lojas com mais dias de promoção deveriam vender mais.  **H7.** Lojas com mais promoções consecutivas deveriam vender mais.**FALSA** Lojas com mais promocoes consecutivas vendem menos<jupyter_code>df4[['promo', 'promo2', 'sales']].groupby( ['promo', 'promo2'] ).sum().reset_index()
aux1 = df4[( df4['promo'] == 1 ) & ( df4['promo2'] == 1 )][['year_week', 'sales']].groupby( 'year_week' ).sum().reset_index()
ax = aux1.plot()

aux2 = df4[( df4['promo'] == 1 ) & ( df4['promo2'] == 0 )][['year_week', 'sales']].groupby( 'year_week' ).sum().reset_index()
aux2.plot( ax=ax )

ax.legend( labels=['Tradicional & Extendida', 'Extendida']);<jupyter_output><empty_output><jupyter_text>**H8.** Lojas abertas durante o feriado de Natal deveriam vender mais.**FALSA** Lojas abertas durante o feriado do Natal vendem menos.<jupyter_code>aux = df4[df4['state_holiday'] != 'regular_day']

plt.subplot( 1, 2, 1 )
aux1 = aux[['state_holiday', 'sales']].groupby( 'state_holiday' ).sum().reset_index()
sns.barplot( x='state_holiday', y='sales', data=aux1 );

plt.subplot( 1, 2, 2 )
aux2 = aux[['year', 'state_holiday', 'sales']].groupby( ['year', 'state_holiday'] ).sum().reset_index()
sns.barplot( x='year', y='sales', hue='state_holiday', data=aux2 );<jupyter_output><empty_output><jupyter_text>**H9.** Lojas deveriam vender mais ao longo dos anos.**FALSA** Lojas vendem menos ao longo dos anos<jupyter_code>aux1 = df4[['year', 'sales']].groupby( 'year' ).sum().reset_index()

plt.subplot( 1, 3, 1 )
sns.barplot( x='year', y='sales', data=aux1 );

plt.subplot( 1, 3, 2 )
sns.regplot( x='year', y='sales', data=aux1 );

plt.subplot( 1, 3, 3 )
sns.heatmap( aux1.corr( method='pearson' ), annot=True );<jupyter_output><empty_output><jupyter_text>**H10.** Lojas deveriam vender mais no segundo semestre do ano.**FALSA** Lojas vendem menos no segundo semestre do ano<jupyter_code>aux1 = df4[['month', 'sales']].groupby( 'month' ).sum().reset_index()

plt.subplot( 1, 3, 1 )
sns.barplot( x='month', y='sales', data=aux1 );

plt.subplot( 1, 3, 2 )
sns.regplot( x='month', y='sales', data=aux1 );

plt.subplot( 1, 3, 3 )
sns.heatmap( aux1.corr( method='pearson' ), annot=True );<jupyter_output><empty_output><jupyter_text>**H11.** Lojas deveriam vender mais depois do dia 10 de cada mês.**VERDADEIRA** Lojas vendem mais depois do dia 10 de cada mes.<jupyter_code>aux1 = df4[['day', 'sales']].groupby( 'day' ).sum().reset_index()

plt.subplot( 2, 2, 1 )
sns.barplot( x='day', y='sales', data=aux1 );

plt.subplot( 2, 2, 2 )
sns.regplot( x='day', y='sales', data=aux1 );

plt.subplot( 2, 2, 3 )
sns.heatmap( aux1.corr( method='pearson' ), annot=True );

aux1['before_after'] = aux1['day'].apply( lambda x: 'before_10_days' if x <= 10 else 'after_10_days' )
aux2 =aux1[['before_after', 'sales']].groupby( 'before_after' ).sum().reset_index()

plt.subplot( 2, 2, 4 )
sns.barplot( x='before_after', y='sales', data=aux2 );<jupyter_output><empty_output><jupyter_text>**H12.** Lojas deveriam vender menos aos finais de semana.**VERDADEIRA** Lojas vendem menos nos final de semana<jupyter_code>aux1 = df4[['day_of_week', 'sales']].groupby( 'day_of_week' ).sum().reset_index()

plt.subplot( 1, 3, 1 )
sns.barplot( x='day_of_week', y='sales', data=aux1 );

plt.subplot( 1, 3, 2 )
sns.regplot( x='day_of_week', y='sales', data=aux1 );

plt.subplot( 1, 3, 3 )
sns.heatmap( aux1.corr( method='pearson' ), annot=True );<jupyter_output><empty_output><jupyter_text>**H13.** Lojas deveriam vender menos durante os feriados escolares.**VERDADEIRA** Lojas vendem menos durante os feriadso escolares, except os meses de Julho e Agosto.<jupyter_code>aux1 = df4[['school_holiday', 'sales']].groupby( 'school_holiday' ).sum().reset_index()
plt.subplot( 2, 1, 1 )
sns.barplot( x='school_holiday', y='sales', data=aux1 );

aux2 = df4[['month', 'school_holiday', 'sales']].groupby( ['month','school_holiday'] ).sum().reset_index()
plt.subplot( 2, 1, 2 )
sns.barplot( x='month', y='sales', hue='school_holiday', data=aux2 );<jupyter_output><empty_output><jupyter_text>4.2.1. Resumo das Hipoteses<jupyter_code>from tabulate import tabulate
tab =[['Hipoteses', 'Conclusao', 'Relevancia'],
      ['H1', 'Falsa', 'Baixa'],  
      ['H2', 'Falsa', 'Media'],  
      ['H3', 'Falsa', 'Media'],
      ['H4', 'Falsa', 'Baixa'],
      ['H5', '-', '-'],
      ['H7', 'Falsa', 'Baixa'],
      ['H8', 'Falsa', 'Media'],
      ['H9', 'Falsa', 'Alta'],
      ['H10', 'Falsa', 'Alta'],
      ['H11', 'Verdadeira', 'Alta'],
      ['H12', 'Verdadeira', 'Alta'],
      ['H13', 'Verdadeira', 'Baixa'],
     ]  
print( tabulate( tab, headers='firstrow' ) )<jupyter_output><empty_output><jupyter_text>4.3. Analise Multivariada  4.3.1. Numerical Attributes<jupyter_code>correlation = num_attributes.corr( method='pearson' )
sns.heatmap( correlation, annot=True );<jupyter_output><empty_output><jupyter_text>4.3.2. Categorical Attributes<jupyter_code># only categorical data
a = df4.select_dtypes( include='object' )

# Calculate cramer V
a1 = cramer_v( a['state_holiday'], a['state_holiday'] )
a2 = cramer_v( a['state_holiday'], a['store_type'] )
a3 = cramer_v( a['state_holiday'], a['assortment'] )

a4 = cramer_v( a['store_type'], a['state_holiday'] )
a5 = cramer_v( a['store_type'], a['store_type'] )
a6 = cramer_v( a['store_type'], a['assortment'] )

a7 = cramer_v( a['assortment'], a['state_holiday'] )
a8 = cramer_v( a['assortment'], a['store_type'] )
a9 = cramer_v( a['assortment'], a['assortment'] )

# Final dataset
d = pd.DataFrame( {'state_holiday': [a1, a2, a3], 
               'store_type': [a4, a5, a6],
               'assortment': [a7, a8, a9] } )
d = d.set_index( d.columns )

sns.heatmap( d, annot=True )<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup