<jupyter_start><jupyter_text>Heroes Of Pymoli Data Analysis* The biggest demographical spender are those in the 20-24 bucket; accounting for $1,114.06 of the total $2388.86.* The largest average spending demographic (on a per item basis) is the 35-39 bucket, with an average of $4.76.* Although the 'Other/Non-Disclosed' bucket make up only 1.91% of the total number of players, they accounted for the largest spender on a 'Avg. Purchase Value' and 'Avg. Purchase Total P/P' basis.* Our peak age demographic falls between 20-24 (44.8%) with secondary groups falling between 15-19 (18.60%) and 25-29 (13.4%).* Of the 1163 active players, the vast majority are male (84%). There also exists, a smaller, but notable proportion of female players (14%).-----  Note* Instructions have been included for each segment. You do not have to follow them exactly, but they are included to help you think through the steps.<jupyter_code># Dependencies and Setup
import pandas as pd

# File to Load (Remember to Change These)
file_to_load = "Resources/purchase_data.csv"

# Read Purchasing File and store into Pandas data frame
purchase_data = pd.read_csv(file_to_load)<jupyter_output><empty_output><jupyter_text>Player Count * Display the total number of players<jupyter_code># using the length of the SN column to calculate total players
total_players = len(purchase_data["SN"].value_counts())
print("Total players = ",total_players)<jupyter_output>Total players =  576<jupyter_text>Purchasing Analysis (Total) * Run basic calculations to obtain number of unique items, average price, etc.* Create a summary data frame to hold the results* Optional: give the displayed data cleaner formatting* Display the summary data frame<jupyter_code># running basic calculations to obtain (i) unique items
unique_items = len((purchase_data["Item ID"]).unique())
# (ii) average price
average_price = (purchase_data["Price"]).mean()
# (iii) purchase count
total_of_purchases = (purchase_data["Purchase ID"]).count()
# (iv) total revenue
total_of_revenue = (purchase_data["Price"]).sum()

# creating a summary dataframe to hold the calculation outputs
summary_df = pd.DataFrame({"Total Unique Items":[unique_items],
                           "Average Item Price":[average_price], 
                           "Total Purchases": [total_of_purchases], 
                           "Total Revenue": [total_of_revenue]})

# basic currency formatting to finesse and give clarity to the data
summary_df.style.format({'Average Item Price':"${:,.2f}",
                         'Total Revenue': '${:,.2f}'})<jupyter_output><empty_output><jupyter_text>Gender Demographics * Percentage and Count of Male Players* Percentage and Count of Female Players* Percentage and Count of Other / Non-Disclosed<jupyter_code># grouping data by gender data
gender_grouping = purchase_data.groupby("Gender")

#counting total screen names, by gender
gender_total = gender_grouping.nunique()["SN"]

# obtaining player percentage by taking total count by gender and / by total player count
player_percentage = gender_total / total_players * 100

# creating dataframe to hold above values
gender_demographics = pd.DataFrame({"% of players": player_percentage, "Total players": gender_total }) 
gender_demographics.round(1)

# sorting '% of players' values descendingly and formatting. I tried to write seperate lines of code for 'sort_values and 'style.format' but nothing happened!
gender_demographics.sort_values(["% of players"], ascending = False).style.format({"% of players":"{:,.2f}",})<jupyter_output><empty_output><jupyter_text>Purchasing Analysis (Gender) * Run basic calculations to obtain purchase count, avg. purchase price, avg. purchase total per person etc. by gender* Create a summary data frame to hold the results* Optional: give the displayed data cleaner formatting* Display the summary data frame<jupyter_code># basic calculations to obtain purchase count by gender
total_purchase_count = gender_grouping["Purchase ID"].count()

# basic calculations to obtain avg. purchase price by gender
avg_purchase_price = gender_grouping["Price"].mean()

# basic calculation to obtain total purchase price by gender
total_purchase_value = gender_grouping["Price"].sum()


# basic calculations to obtain  avg. purchase total per person by gender
avg_purchase_total_pp = total_purchase_value/gender_total

# creating dataframe to house above calculated values
purchase_analysis_summary = pd.DataFrame({"Total Purchase Count": total_purchase_count,
                                          "Avg. Purchase Value": total_purchase_value,
                                          "Avg. Purchase Price": avg_purchase_price,
                                          "Avg. Purchase Total P/P": avg_purchase_total_pp})

# making sure my index column / name is Gender
purchase_analysis_summary.index.name = "Gender"

# basic currency formatting to finesse and give clarity to the data
purchase_analysis_summary.sort_values(["Total Purchase Count"], ascending = False).style.format({"Avg. Purchase Value": "${:,.2f}", "Avg. Purchase Price": "${:,.2f}",
                                        "Avg. Purchase Total P/P": "${:,.2f}"})<jupyter_output><empty_output><jupyter_text>Age Demographics * Establish bins for ages* Categorize the existing players using the age bins. Hint: use pd.cut()* Calculate the numbers and percentages by age group* Create a summary data frame to hold the results* Optional: round the percentage column to two decimal points* Display Age Demographics Table<jupyter_code># bins for my age values / groupings
age_bins = [0, 9.90, 14.90, 19.90, 24.90, 29.90, 34.90, 39.90, 99999]
grouping_names = ["<10", "10-14", "15-19", "20-24", "25-29", "30-34", "35-39", "40+"]

# sorting values, based on the above bins
purchase_data["Age Groupings"] = pd.cut(purchase_data["Age"],age_bins, labels=grouping_names)
purchase_data

# Dataframe to inc. Age Groupings and group using it.
grouped_age = purchase_data.groupby("Age Groupings")

#counting total players, using SN column and the nunique function.
total_age_count = grouped_age["SN"].nunique()

# calculating the %s by Age Group
percentages_by_age_groupings = (total_age_count/total_players) * 100

# summary dataframe to display sought values
summary_results = pd.DataFrame({"% of players": percentages_by_age_groupings, "Total": total_age_count})

# basic currency formatting to finesse and give clarity to the data
summary_results.style.format({"% of players":"{:,.2f}"})<jupyter_output><empty_output><jupyter_text>Purchasing Analysis (Age) * Bin the purchase_data data frame by age* Run basic calculations to obtain purchase count, avg. purchase price, avg. purchase total per person etc. in the table below* Create a summary data frame to hold the results* Optional: give the displayed data cleaner formatting* Display the summary data frame<jupyter_code># calculating total purchase count by gender
purchases_per_ag = grouped_age["Purchase ID"].count()

# calculating avg. purchase price by gender
avg_purchase_price_per_ag = grouped_age["Price"].mean()

# calculating the avg. purchase total by gender
total_purchase_value_per_ag = grouped_age["Price"].sum()

# calculating the avg. purchase p/p
avg_purchase_per_person_per_ag = total_purchase_value_per_ag/total_age_count

# summary dataframe to hold sought values, calcuated above.
purchasing_analysis_age_summary = pd.DataFrame({"Purchase Count": purchases_per_ag,
                                          "Avg. Purchase Price": avg_purchase_price_per_ag,
                                          "Total Purchase Value": total_purchase_value_per_ag,
                                          "Avg. Purchase Total P/P": avg_purchase_per_person_per_ag})

# this code is not required, as by default the header would show unless = None. I am displaying this code to show intention of displaying the index heading.
# in this case Age Groupings.
purchasing_analysis_age_summary.index.name = "Age Groupings"

# basic currency formatting to finesse and give clarity to the data
purchasing_analysis_age_summary.style.format({"Purchase Count": "{:,.0f}", "Avg. Purchase Price": "${:,.2f}",
                                        "Total Purchase Value": "${:,.2f}", "Avg. Purchase Total P/P": "${:,.2f}"})<jupyter_output><empty_output><jupyter_text>Top Spenders * Run basic calculations to obtain the results in the table below* Create a summary data frame to hold the results* Sort the total purchase value column in descending order* Optional: give the displayed data cleaner formatting* Display a preview of the summary data frame<jupyter_code># grouping data by screen name
top_spenders_grouping = purchase_data.groupby("SN")

# calculating total buyer purchase using names
buyers_total_purchase_count = top_spenders_grouping["Purchase ID"].count()

# calculating average buyer purchase by name
avg_purchase_by_buyer = top_spenders_grouping["Price"].mean()

#calculating purchase total
purchase_total = top_spenders_grouping["Price"].sum()

# summary dataframe to house calculated values
top_spenders_summary = pd.DataFrame({"Purchase Count": buyers_total_purchase_count,
                                     "Avg. Purchase Price": avg_purchase_by_buyer,
                                     "Total Purchase Value":purchase_total})

# sorting data by Top Purchase Value
formatted_top_spenders = top_spenders_summary.sort_values(["Total Purchase Value"], ascending=False).head()

# this code is not required, as by default the header would show unless = None. I am displaying this code to show intention of displaying the index heading.
# in this case SN.
formatted_top_spenders.index.name = "SN"

# basic currency formatting to finesse and give clarity to the data
formatted_top_spenders.style.format({"Avg. Purchase Price":"${:,.2f}",
                                     "Average Purchase Price":"${:,.2f}",
                                     "Total Purchase Value":"${:,.2f}"})<jupyter_output><empty_output><jupyter_text>Most Popular Items * Retrieve the Item ID, Item Name, and Item Price columns* Group by Item ID and Item Name. Perform calculations to obtain purchase count, item price, and total purchase value* Create a summary data frame to hold the results* Sort the purchase count column in descending order* Optional: give the displayed data cleaner formatting* Display a preview of the summary data frame<jupyter_code># datafram to house key information on items
popular_items = purchase_data[["Item ID", "Item Name", "Price"]]

# sorting / grouping the data by Item ID and Item Name
grouped_item_unique_ids = popular_items.groupby(["Item ID", "Item Name"])
            
# calculating total purchase quantity for each item
item_purchase_count = grouped_item_unique_ids["Price"].count()
                              
# calculating the purchase value per item
per_item_purchase_value = (grouped_item_unique_ids["Price"].sum())

# calculating the individual item price
individual_item_price = per_item_purchase_value/item_purchase_count

# dataframe to house obtained values, from above calculations
most_popular_items = pd.DataFrame({"Purchase Count": item_purchase_count,
                                  "Item Price": individual_item_price,
                                  "Total Purchase Value": per_item_purchase_value}) 

# grouping data decsendingly to show top 5 popular items, using Purchase Count
most_popular_formatted = most_popular_items.sort_values(["Purchase Count"], ascending=False).head()

# basic currency formatting to finesse and give clarity to the data
most_popular_formatted.style.format({"Item Price":"${:,.2f}",
                                "Total Purchase Value":"${:,.2f}"})<jupyter_output><empty_output><jupyter_text>Most Profitable Items * Sort the above table by total purchase value in descending order* Optional: give the displayed data cleaner formatting* Display a preview of the data frame<jupyter_code># sorting above table by Total Purchase Value descendingly
most_popular_formatted = most_popular_items.sort_values(["Total Purchase Value"], ascending=False).head()

# basic currency formatting to finesse and give clarity to the data
most_popular_formatted.style.format({"Item Price":"${:,.2f}",
                                "Total Purchase Value":"${:,.2f}"})<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0901047162919068, 'fraction_numerical': 0.011851611332088643, 'mean_word_length': 4.283018867924528, 'pattern_counts': {'":': 38, '<': 41, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '325484', 'license': 'ADSL', 'n_tokens_mistral': 3553, 'n_tokens_neox': 3303, 'n_words': 1229, 'path': 'HeroesOfPymoli_starter.ipynb', 'repo_name': 'SaltireSequence/pandas-challange', 'size': '12319'}