import streamlit as st
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
#Load data
fraud = pd.read_csv('fraud_test.csv')
# Define the percentage of data you want to sample
sample_percentage = 50 # Adjust this percentage as needed
# Randomly sample the data based on the percentage
data = fraud.sample(frac=sample_percentage/100, random_state=22)
# def annotate_bar(ax, custom_y_func, font_size=14):
# for p in ax.patches:
# # Calculate annotation
# value = str(round(p.get_height(), 1))
# x = (p.get_x() + p.get_width() / 2) * 0.99
# y = ((p.get_y() + p.get_height() / 2) * 0.99)
# y = custom_y_func(y)
# ax.annotate(
# value,
# (x, y),
# color="black",
# size=font_size, ha='center', va='center'
# )
def eda_page():
st.title("Eksploratory Data Analysis")
st.write('Analyze the DataFrame for Better Understanding')
st.markdown("
Top 10 Transaction Amount
", unsafe_allow_html=True)
# TOP Transaction Amount
columns = ['job', 'state', 'city', 'merchant']
fraud_labels = ['Not Fraud', 'Fraud']
for col in columns:
st.subheader(f"Top 10 transaction amount by {col}")
fig, ax = plt.subplots(1, 2, figsize=(30, 5))
for i, fraud_label in enumerate(fraud_labels):
temp_data = data[data['is_fraud'] == (0 if fraud_label == 'Not Fraud' else 1)]
top = temp_data.groupby(col)['amt'].sum().nlargest(10)
ax[i].bar(top.index, top.values, color='#a1c9f4')
ax[i].set_title(fraud_label)
ax[i].set_xlabel(col)
ax[i].set_ylabel('Amount')
if col == 'state':
ax[i].tick_params(axis='x', rotation=0)
else:
ax[i].tick_params(axis='x', rotation=90)
st.pyplot(fig)
st.write("**Explanation**:")
markdown_text = """
* From the top 10 transaction amount by job we can see `Science Writer` have the most fraud with over 10.000 transaction amount meanwhile `Film/Video editor` are the most non fraud with almost 160.000 transaction
* From the top 10 transaction amount by state we can see `NY` have the most fraud with almost 60.000 transaction amount meanwhile `TX`are the most non fraud with above 1.400.000 transaction
* From the top 10 transaction amount by city we can see `Camden` have the most fraud with over 10.000 transaction amount meanwhile `Meridian` are the most non fraud with almost 100.000 transaction
* From the top 10 transaction amount by merchant we can see `Heathcote, Yost and Kertzmann` have most fraud with almost 10.000 transaction amount meanwhile `Killback-LLC` are the most non fraud with over 80.000 transaction
"""
st.markdown(markdown_text)
st.markdown("Top 10 Transaction Count
", unsafe_allow_html=True)
# By Transaction count
columns = ['job', 'state', 'city', 'merchant']
columns_name = ['Job', 'State', 'City', 'Merchant']
fraud = ['Not Fraud', 'Fraud']
for col, name in zip(columns, columns_name):
st.subheader(f"Top 10 transaction by {name}")
fig, ax = plt.subplots(1, 2, figsize=(30, 5))
sns.set_palette("pastel")
for i, fraud_label in enumerate(fraud):
temp_data = data[data['is_fraud'] == (0 if fraud_label == 'Not Fraud' else 1)]
top = temp_data.groupby(col).size().nlargest(10)
ax[i].bar(top.index, top.values, color='#a1c9f4')
ax[i].set_title(fraud_label)
ax[i].set_xlabel(name)
ax[i].set_ylabel('Count')
if col == 'state':
ax[i].tick_params(axis='x', rotation=0)
else:
ax[i].tick_params(axis='x', rotation=90)
st.pyplot(fig)
st.write("") # Add a blank line
st.write("**Explanation**:")
markdown_text = """
* From the top 10 transaction by job we can see `Color Technologist` have the most fraud with over 20 transaction meanwhile `Film/Video editor` are the most not fraud with over 2.000 transaction
* From the top 10 transaction by state we can see `NY` have the most fraud with over 80 transaction meanwhile `TX`are the most not fraud with 20.000 transaction
* From the top 10 transaction by city we can see `Camden` have the most fraud over 20 transaction meanwhile `Birmingham` are the most not fraud with almost 1.200 transaction
* From the top 10 transaction by merchant we can see `Healthcore LLC.` have most fraud with 10 transaction meanwhile `Killback LLC.` are the most not fraud with almost 1.000 transaction
"""
st.markdown(markdown_text)
st.markdown("Total Number and Amount for Fraud and Non Fraud Transaction
", unsafe_allow_html=True)
def annotate_bar(ax, custom_y_func, font_size=14):
for p in ax.patches:
value = str(round(p.get_height(), 1))
x = (p.get_x() + p.get_width() / 2) * 0.99
y = ((p.get_y() + p.get_height() / 2) * 0.99)
y = custom_y_func(y)
ax.annotate(value, (x, y), color="black", size=font_size, ha='center', va='center')
# Fraud and Not Fraud Transactions
st.header("Fraud and Not Fraud Transactions Count")
data_fraud_count = data['is_fraud'].apply(lambda x: "Fraud" if x == 1 else 'Not Fraud').value_counts().reset_index()
fig, ax = plt.subplots(figsize=(15, 5))
sns.barplot(data=data_fraud_count, x='is_fraud', y='count', color='#c6def8', ax=ax)
annotate_bar(ax, lambda y: 15000 if y < 10000 else y, font_size=14)
ax.set_title("Total number of transaction for fraud and not fraud transaction", fontsize=12, fontweight='bold')
ax.set_ylabel("Transaction count")
ax.set_xticklabels(ax.get_xticklabels(), rotation=0)
st.pyplot(fig)
# Fraud and Not Fraud Amount
st.header("Fraud and Not Fraud Transactions Amount")
data_fraud_amount = data.groupby('is_fraud')['amt'].sum().reset_index()
fig, ax = plt.subplots(figsize=(15, 5))
sns.barplot(data=data_fraud_amount, x='is_fraud', y='amt', color='#c6def8', ax=ax)
annotate_bar(ax, lambda y: 1900000 if y < 1200000 else y, font_size=12)
ax.set_title("Total transaction amount for fraud and not fraud transaction", fontsize=12, fontweight='bold')
ax.set_ylabel("Transaction amount")
ax.set_xticklabels(['Not Fraud', 'Fraud'], rotation=0)
st.pyplot(fig)
st.write("**Explanation**:")
markdown_text = """
Based on visualisation above:
* There is 276743 total number of transaction `not fraud` and 1117 `fraud` transaction
* There is 18745296.5 total transaction amount of `not fraud` and 1117 `fraud` transaction
"""
st.markdown(markdown_text)
# Calculate age
data['dob'] = pd.to_datetime(data['dob'])
data['age'] = (2020 - data['dob'].dt.year)
def apply_age_group(age):
if age <= 18:
return 'Teenager'
elif age <= 25:
return "Young Adult"
elif age <= 64:
return "Adult"
else:
return "Elder"
data['age_group'] = data['age'].apply(apply_age_group)
# Overview of dataset by month, gender, and category
st.header("Overview of dataset by Age, gender, and category")
columns = ['gender', 'category', 'age', 'age_group']
columns_name = ['gender', 'category', 'age', 'age group']
name = ['Not Fraud', 'Fraud']
for col in columns:
st.subheader("Distribution of transaction by " + columns_name[columns.index(col)])
fig, ax = plt.subplots(1, 2, figsize=(15, 5)) # Create a subplot with 2 columns
for i in range(0, 2):
data_1 = data[data['is_fraud'] == i]
if col == 'gender':
ax[i].pie(data_1[col].value_counts(), labels=['Female', 'Male'], autopct='%1.1f%%')
elif col == 'age_group':
ax[i].pie(data_1[col].value_counts(), labels=data_1[col].value_counts().index, autopct='%1.1f%%')
elif col == 'category':
sns.countplot(data=data_1, y=col, order=data_1[col].value_counts().index, ax=ax[i])
else:
sns.histplot(data=data_1, x=col, ax=ax[i])
ax[i].set_title(name[i])
ax[i].set_xlabel(columns_name[columns.index(col)])
if col == 'category':
ax[i].set_xticklabels(ax[i].get_xticklabels(), rotation=90)
st.pyplot(fig)
st.write("**Explanation**:")
markdown_text = """
Based on visualisation above we can see:
- There is 54,8% transaction of `female` and 45,2% transaction of `male` in `not fraud` and `fraud`
- Most distribution of `not fraud` transaction by category is from `gas_transport` meanwhile in fraud is from shopping_net
- In distribution transaction by age mostly between 30-40 in `fraud` and between 45-50 for `not fraud`
- By age group mostly `not fraud` transaction is from Adult with 73,9% and `fraud` also from Adult with 74,6%
"""
st.markdown(markdown_text)