<jupyter_start><jupyter_text>Final Project, Part 2 <NAME> The project is done in a Team of 2. The team mates and their details are:  <NAME> (tiwari5) <NAME> (ppdoshi2) While this submission is done by me, my teammate Shraddha will submit her individual jupyter notebook as instructed in the assignment details. In this part of our Final Project, we have developed an interactive Dashboard in terms of a Domain expert as well as explanation for using the interactive Dashboard:  Getting our usual libraries:<jupyter_code>import matplotlib.pyplot as plt  # For creating and manipulating figures and plotting areas
import matplotlib # For creating plots
import numpy as np # For numeric representation of the data
import pandas as pd # For DataFrame manipulation
%matplotlib inline
import ipywidgets  # For interactivity
from ipywidgets import Dropdown # for the extra interactive widget part
from ipywidgets import VBox, HBox, Layout # for the extra interactive widget part
import bqplot
from bqplot import pyplot as plot
from bqplot import Tooltip
from bokeh.models import HoverTool
from bokeh.io import output_notebook
from bokeh.plotting import show
import ipywidgets as widgets<jupyter_output><empty_output><jupyter_text>Getting the data:<jupyter_code>with open('./flipkart_fashion_products_dataset.json', encoding='utf-8') as inputfile:
    df = pd.read_json(inputfile)

df.to_csv('flipkart_fashion_products_dataset_1.csv', encoding='utf-8', index=False)
df.head(5)
df = df.astype({'actual_price':'string','selling_price':'string','average_rating':'string', 'discount':'string'})
df['actual_price'] = df['actual_price'].str.replace(',', '')
df['selling_price'] = df['selling_price'].str.replace(',', '')
df['discount'] = df['discount'].str.replace('% off', '')

df['actual_price'] = pd.to_numeric(df['actual_price'], errors='coerce')
df['selling_price'] = pd.to_numeric(df['selling_price'], errors='coerce')
df['average_rating'] = pd.to_numeric(df['average_rating'], errors='coerce')
df['discount'] = pd.to_numeric(df['discount'], errors='coerce')<jupyter_output><empty_output><jupyter_text>Coalation of similar subcategories in the data:<jupyter_code>df['average_rating'] = df['average_rating'].replace(np.nan, 0)
df['discount'] = df['discount'].replace(np.nan, 0)

df['sub_category'].replace(to_replace = ['Clothing Accessories', 'Crocks Club Clothing and Accessories',
'Inspire Clothing and Accessories', 'INSPIRE Clothing and Accessories', 'Roy Clothing and Accessories', 'Uber Urban Clothing and Accessories'],
 value = 'Clothing and Accessories',
 inplace = True)

df['sub_category'].replace(to_replace = ['Kurtas, Ethnic Sets and Bottoms'],
 value = 'Ethnic Wear',
 inplace = True)

df['sub_category'].replace(to_replace = ['Blazers, Waistcoats and Suits'],
 value = 'Formal Wear',
 inplace = True)

df['sub_category'].replace(to_replace = ['Sleepwear', 'Tracksuits'],
 value = 'Sleep Wear',
 inplace = True)

df['sub_category'].replace(to_replace = ["Men's Footwear"],
 value = 'Footwear',
 inplace = True)

df['sub_category'].replace(to_replace = ['SUNSHOPPING Bags, Wallets & Belts', 'Sunshopping Bags, Wallets & Belts', 'Winsome Deal Bags, Wallets & Belts', 
                                        'YOFAMA Bags, Wallets & Belts', 'Brand Trunk Bags, Wallets & Belts', 'mentiezi Bags, Wallets & Belts'],
 value = 'Bags, Wallets & Belts',
 inplace = True)<jupyter_output><empty_output><jupyter_text>Exploring values of Features at a granular / unique level:<jupyter_code>df['discount'].unique()
df['average_rating'].unique()<jupyter_output><empty_output><jupyter_text>Creating a new categorical variable for rating groups:<jupyter_code>rating_category = pd.cut(df.average_rating,bins=[0,1.0,2.0,3.0,4.0,5.0],labels=['1-Star','2-Star','3-Star','4-Star','5-Star'])
df.insert(6,"Rating_Group",rating_category)
df.head(5)<jupyter_output><empty_output><jupyter_text>Creating the static visualization of our first view of the Dashboard:<jupyter_code>stackedBar_data = df[['sub_category', 'Rating_Group']].value_counts().reset_index().rename(columns = {0: 'value'})
stackedBar_data = stackedBar_data.loc[stackedBar_data['Rating_Group'] != 'Unknown']
stackedBar_data.pivot(index='sub_category', columns='Rating_Group', values='value').plot(kind='bar', stacked = True, figsize=(15,10), title = 'Category vs Ratings', log=True)<jupyter_output><empty_output><jupyter_text>Creating bar chart for Average Selling Price per Brand:<jupyter_code>fig, ax = plt.subplots(figsize=(20,15)) 

bar1_data = df[df['sub_category']== 'Formal Wear'].groupby('brand')['selling_price'].mean()
ax.bar(bar1_data.index, bar1_data.values)
ax.set_xlabel('Brand', fontsize = 15)
ax.set_ylabel('Average Selling Price', fontsize = 15)
ax.set_title('Average Selling Price of products per Brand', fontsize = 30)<jupyter_output><empty_output><jupyter_text>Creating the Interactivity for the dashboard!<jupyter_code># Code for stacked bar chart

figa = plot.figure(title = 'Category vs Ratings')

df1 = df.groupby(["sub_category", "Rating_Group"])._id.count().unstack('Rating_Group')

sc_x = bqplot.OrdinalScale()
sc_y = bqplot.LinearScale()
scales = {"x": sc_x, "y": sc_y}


categories = plot.bar(x = df1.index, 
                 y= [df1['1-Star'],df1['2-Star'],df1['3-Star'],df1['4-Star'],df1['5-Star']],
                 scales= scales,
                 labels = ['1-Star','2-Star','3-Star','4-Star','5-Star'],
                 interactions = {'click': 'select', 'hover': 'tooltip'},
                 anchor_style = {'fill': 'white'},
                 selected_style={'stroke': 'white', 'stroke-width': 3},
                 unselected_style={'opacity':0.5},
                 display_legend = True)

categories.type = "stacked"
categories.colors = bqplot.CATEGORY10


plot.xlabel("Category")
plot.ylabel("Ratings")
figa.axes[0].tick_rotate = -30
figa.axes[0].tick_style = {'text-anchor': 'end', 'offset': '40px', 'font-size': 10}
figa.axes[0].label_offset = '55px'
figa.legend_location = 'top-left'
figa.legend_text = {'font-size': 12}
figa.legend_style = {'width': 'auto'}

#####################################################################
y_range = widgets.IntRangeSlider(value=[1,15000],
                        min=1,
                        max=15000,
                        step=(15000 - 1) / 100,
                        description="Y Axis",
                        disabled=False,
                        continuous_update=False,
                        orientation='horizontal',
                        readout=True)

def updateYAxis(change1):
    #Update Y-axis min/max value here
    if change1['type'] == 'change' and change1['name'] == 'value':
        sc_y.min = change1['new'][0]
        sc_y.max = change1['new'][1]
    

y_range.observe(updateYAxis)
figa = widgets.VBox([figa, y_range])

#####################################################################
# referenced the above version of code for y slider from here:
# https://github.com/bqplot/bqplot/issues/712



# Code for the vertical bar chart for average selling price

figb = plot.figure(title = "Average Selling Price of products per Brand")

figb.layout.height = "400px"
figb.layout.width = "600px"

subset = df.loc[df['category'] == 'Footwear']

price_mean = subset.groupby("brand").selling_price.mean()


price_plot = plot.bar(x = price_mean.index.tolist(), 
                       y= price_mean.values.tolist(), 
                       orientation = 'vertical',
                      tick_style ={'font-size': 100})

#price_plot.colors = ["#06C2AC"]
price_plot.colors = "palevioletred"
plot.xlabel("Brand")
plot.ylabel("Average Selling Price")

figb.axes[0].tick_rotate = -60
figb.axes[0].tick_style = {'text-anchor': 'end', 'offset': '40px', 'font-size': 10}
figb.axes[0].label_offset = '40px'

# Code for the vertical bar chart for average actual price

figc = plot.figure(title = "Average Actual Price of products per Brand")

figc.layout.height = "500px"
figc.layout.width = "700px"

subset1 = df.loc[df['category'] == 'Footwear']

price_mean1 = subset.groupby("brand").actual_price.mean()


price_plot1 = plot.bar(x = price_mean1.index.tolist(), 
                       y= price_mean1.values.tolist(), 
                       orientation = 'vertical',
                      tick_style ={'font-size': 100})

price_plot1.colors = ["#06C2AC"]
plot.xlabel("Brand")
plot.ylabel("Average Actual Price")

figc.axes[0].tick_rotate = -60
figc.axes[0].tick_style = {'text-anchor': 'end', 'offset': '40px', 'font-size': 10}
figc.axes[0].label_offset = '40px'<jupyter_output><empty_output><jupyter_text>Creating output placeholders for tooltips:<jupyter_code>out = ipywidgets.Output()
out1 = ipywidgets.Output(layout={'border': '1px solid black', 
                                 'margin': '0 0 0 0'})
out2 = ipywidgets.Output(layout={'border': '1px solid black', 
                                 'margin': '0 0 0 0'})
out3 = ipywidgets.Output(layout={'border': '1px solid black', 
                                 'margin': '0 0 0 0'})<jupyter_output><empty_output><jupyter_text>Adding the code for interactivity in the visualizations:<jupyter_code># Code for tooltip for the stacked bar chart
def on_hover_categories(_, event):
    out1.clear_output()
    with out1:
        print(f"Category: {event['data']['x']}\n"\
              f"Rating Group: {df1.columns[event['data']['colorIndex']]}\n"\
              f"Rating Count: {event['data']['y']}\n")
    categories.tooltip = out1

# Code for tooltip for the bar chart    
def on_hover_selling_price_mean(_, event):
    out2.clear_output()
    with out2:
        print(f"Brand: {event['data']['x']}\n"
              f"Average Selling Price: {event['data']['y']}\n")
    price_plot.tooltip = out2

# Code for tooltip for the bar chart    
def on_hover_actual_price_mean1(_, event):
    out3.clear_output()
    with out3:
        print(f"Brand: {event['data']['x']}\n"
              f"Average Actual Price: {event['data']['y']}\n")
    price_plot1.tooltip = out3

# Calback function to interact with bar plot
def on_selected(self, change, df):
    #print(change, self)
    category_selected = None
    if len(self.selected) == 0:
            label.value = 'No data selected!!'
            return
    for mark in self.selected:
        category_selected = self.x[mark]

    subset = df.loc[df['sub_category'] == category_selected]

    price_mean = subset.groupby("brand").selling_price.mean()
    
    price_plot.x = price_mean.index.tolist()
    price_plot.y = price_mean.values.tolist()
    
    subset1 = df.loc[df['sub_category'] == category_selected]

    price_mean1 = subset.groupby("brand").actual_price.mean()
    
    price_plot1.x = price_mean1.index.tolist()
    price_plot1.y = price_mean1.values.tolist()

categories.on_hover(on_hover_categories)
categories.on_element_click(lambda _, x: on_selected(_, x, df))
price_plot.on_hover(on_hover_selling_price_mean)
price_plot1.on_hover(on_hover_actual_price_mean1)<jupyter_output><empty_output><jupyter_text>The Dashboard  How to use it and what does it show? This visualization gives the user an idea of how all Products within each Subcategory fare in terms of Consumer Ratings. The Bar chart is a stacked visualization, wherein each color code depicts the distribution of the 5 Categories of Rating Groups. - The height of each bar within the chart represents the total ratings received by the products listed under that Subcategory. However, each separate color-coded section within a single stacked bar denotes the division of star ratings. - Upon hovering on any section of the visualization, the user can see the Category being highlighted with the hover, the Rating Group, and the count of ratings under that Rating Group. - The user can also adjust the scale of the Y-axis to closely examine the Subcategories and their Rating Groups. A slider with this functionality is present just below the graph which enables the user to perform the scaling action on the dynamic visualization. - While clicking on the individual bars, the visualization provides an interactive aspect of drilling down to a more granular level. The selection of any SubCategory in the stacked bar chart will deliver two more bar charts below the dashboard.  Each of these bar charts is a deeper view of the main dashboard graph. - The first bar graph represents the view of how different brands are competing in the area of Selling Price for their individual products under the clicked Subcategory. This is done by a comparison of the average Selling Price calculated and plotted against the Brands under the SubCategory. - Similarly, the second graph gives an idea of the Actual Price of products listed by their Brands under the clicked Subcategory. This is plotted based on how well the brands fare with the average Actual Price calculated for every brand under the Subcategory. With a comparative view, the user can understand the difference in Brand competition in the market for any selected Subcategory that they select. It provides insights and patterns to understand the placement and pricing of products for improvement.  Creating the dashboard by combining all three visualizations:<jupyter_code>figa.layout.min_width = '100%'
figb.layout.min_width = '100%'
figc.layout.min_width = '100%'
my_dashboard = ipywidgets.VBox([figa, figb, figc])
my_dashboard.layout.width = 'auto'
# my_dashboard.layout.display = 'flex'
display(my_dashboard)
type(my_dashboard)<jupyter_output><empty_output><jupyter_text>Creating a new categorical variable for dicount range:<jupyter_code>discount_range = pd.cut(df.discount,bins=[0,10,20,30,40,50,60,70,80,90],labels=['Below 10%','10%-20%','20%-30%','30%-40%','40%-50%', '50%-60%', '60%-70%', '70%-80%', 'Above 80%'])
df.insert(6,"Discount Range",discount_range)
df.head()<jupyter_output><empty_output><jupyter_text>Here, we had tried to create a line chart analysis, however, it did not quite work out:<jupyter_code># figd = plt.figure(constrained_layout=True, figsize=(20,15))
# gs2 = figd.add_gridspec(1, 1)

# ax3 = figd.add_subplot(gs2[0,0])
# grouped_data1= df[df['Discount Range']== '10%-20%'].groupby('sub_category')._id.count()
# ax3.plot(grouped_data1.index, grouped_data1.values, 'b', label='10%-20%')

# grouped_data2= df[df['Discount Range']== '20%-30%'].groupby('sub_category')._id.count()
# ax3.plot(grouped_data2.index, grouped_data2.values, 'r', label='20%-30%')

# grouped_data3= df[df['Discount Range']== '30%-40%'].groupby('sub_category')._id.count()
# ax3.plot(grouped_data3.index, grouped_data3.values, 'y', label='30%-40%')

# ax3.legend()
# plt.xticks(rotation=45, fontsize = 15) 
# plt.yticks(fontsize = 15) 
# ax3.set_xlabel('Sub Category', fontsize= 25)
# ax3.set_ylabel('Number of products', fontsize= 25)
# ax3.set_title('Number of products/Sub Category', fontsize=30)
import seaborn as sns
# plt.figure(constrained_layout=True, figsize=(20,15))
# sns.countplot(x=df['sub_category'],data=df, palette='rainbow',hue=df['Discount Range'])
# plt.xticks(rotation=45, fontsize = 15) 
# plt.yticks(fontsize = 15) 
# plt.legend(loc='upper right')
# plt.ylim(200, 4000)<jupyter_output><empty_output><jupyter_text>Interactive Collected Bar Chart: - The Chart below is a representation of Category or Subcategory with the percentage of their products placed in the different discount ranges. The user has the option of selecting the view of a Category distinction or a Subcategory distinction. The height of all the bars denotes the percentage of products listed under different discount ranges. A legend of color-coded discount ranges is provided within the Collective Bar Chart for easy understanding.- This Collected Bar Chart presents a range of percentages within each Category or Subcategory as selected by the user, to give an overall view of products sold with discounts. The graph can give an idea of understanding the most common categories or subcategories of products being sold with specific discount ranges. The user also has an option of changing the color code of the bars, by clicking on the next dropdown and selecting a different color scheme for the Bar Chart.<jupyter_code>plot_options = ['Category', 'Sub Category']

@ipywidgets.interact(selection = plot_options, color = ['deep', 'muted', 'pastel', 'bright', 'dark', 'colorblind', 'rainbow'])
def plot_dicount_range(selection, color):
    plt.figure(constrained_layout=True, figsize=(20,15))
    
    if selection == 'Category':
        discount_counts = (df.groupby(['Discount Range'])['category'].value_counts(normalize=True).rename('percentage').mul(100).reset_index().sort_values('category'))
        sns.barplot(x="category", y="percentage", hue="Discount Range", data=discount_counts, palette = color)
        plt.xticks(rotation=90, fontsize = 15) 
        plt.yticks(fontsize = 15)
        plt.xlabel("Category", fontsize = 15)
        plt.ylabel("Percentage of Products", fontsize = 15)
        plt.title("Percentage of products belonging to different Discount Range per Category", fontsize =15)
        plt.legend(loc='upper right')

    elif selection == 'Sub Category':
        discount_counts = (df.groupby(['Discount Range'])['sub_category'].value_counts(normalize=True).rename('percentage').mul(100).reset_index().sort_values('sub_category'))
        sns.barplot(x="sub_category", y="percentage", hue="Discount Range", data=discount_counts, palette = color)
        plt.xticks(rotation=90, fontsize = 15) 
        plt.yticks(fontsize = 15)
        plt.xlabel("Sub Category", fontsize = 15)
        plt.ylabel("Percentage of Products", fontsize = 15)
        plt.title("Percentage of products belonging to different Discount Raange per Sub Category", fontsize =15)
        plt.legend(loc='upper right')
        
        
# https://towardsdatascience.com/a-complete-guide-to-plotting-categorical-variables-with-seaborn-bfe54db66bec<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13518207282913167, 'fraction_numerical': 0.021456582633053223, 'mean_word_length': 4.59066708424679, 'pattern_counts': {'":': 2, '<': 60, '<?xml version=': 0, '>': 60, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '338650', 'license': 'Apache-2.0', 'n_tokens_mistral': 5822, 'n_tokens_neox': 5448, 'n_words': 1515, 'path': 'doshi_prachi_FinalProject/doshi_prachi_final_project_part2.ipynb', 'repo_name': 'PrachiDoshi22/PrachiDoshi22.github.io', 'size': '17871'}