-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
237 lines (164 loc) · 8.33 KB
/
Copy pathapp.py
File metadata and controls
237 lines (164 loc) · 8.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from main import data_reading
from numeric_information import (Describing_numeric_column, calculate_skew_and_plot_kdeplot, outlier_detection,missing_value_calculation, missing_value_treatment)
from categorical_information import counting_information, plot_countplot
st.set_page_config(page_title="EDA Tool", layout = "wide", page_icon="📊")
st.title("EDA TOOL for Data Analysis")
uploaded_file = st.file_uploader("Upload Your csv File", type = ["csv"])
if uploaded_file is None:
st.info("👆 Please upload a CSV file to get started.")
st.stop()
@st.cache_data
def load_data(uploaded_file):
return data_reading(file = uploaded_file)
dataframe = load_data(uploaded_file)
st.success(f"✅ File uploaded successfully! **{uploaded_file.name}**")
st.sidebar.title("📊 EDA Tool")
st.sidebar.markdown("---")
menu_options = st.sidebar.selectbox("Select options",["DataFrame","Columns"])
# DataFrame Information
if menu_options == "DataFrame":
st.title("DataFrame Information")
st.subheader("🔷 Shape of DataFrame")
col1, col2 = st.columns(2)
col1.metric("Rows", dataframe.shape[0])
col2.metric("Columns", dataframe.shape[1])
# Column Info
st.subheader("🔷 Column Information")
info_df = pd.DataFrame({
"Column":dataframe.columns,
"Datatype": dataframe.dtypes.values,
"Non-null Count": dataframe.count().values,
"Null count": dataframe.isna().sum().values,
"Null Percentage": (dataframe.isna().sum().values/ len(dataframe)*100).round(2)
})
st.dataframe(info_df, use_container_width=True)
#Sample Rows
st.subheader("🔷 Sample Rows")
sample_number = st.number_input("Enter number of sample rows", min_value = 1, max_value= len(dataframe), value = 5)
if st.button("show sample"):
st.dataframe(dataframe.sample(sample_number), use_container_width= True)
# duplicate row identifcation
st.subheader("🔷 Duplicate row Identification")
if st.button("Identiy the duplicate value"):
st.session_state.dup_detected = True
if st.session_state.get("dup_detected", False):
duplicate_count = dataframe.duplicated().sum()
Duplicate_percentage = (duplicate_count / dataframe.shape[0])*100
dc1,dc2 = st.columns(2)
dc1.metric("Duplicate Rows", duplicate_count)
dc2.metric("Duplicate Percentage", Duplicate_percentage)
if duplicate_count > 0:
st.warning(f"⚠️ {duplicate_count} duplicate rows found.")
keep = st.selectbox(
"Which Values to Keep",
options = ["first", "last", "Drop All"]
)
if st.button("Remove Duplicates"):
keep_val = False if keep == "Drop All" else keep
dataframe.drop_duplicates(keep = keep, inplace = True)
st.session_state.dup_detected = False
st.success(f"✅ Duplicate rows removed! New shape: {dataframe.shape}")
# Section 2 Column Information
elif menu_options == "Columns":
st.title("Column Analysis")
column = st.selectbox("Select Column", dataframe.columns)
numeric_dtype = ["int64", "float64", "int32","float32"]
categorical_dtype = ["object"]
if dataframe[column].dtype in numeric_dtype:
st.markdown("🔢 Numeric Column")
# Basic Description
st.subheader("📌 Basic Description")
mean, std_dev = Describing_numeric_column(dataframe, column)
st.dataframe(dataframe[column].describe().to_frame(), use_container_width= True)
c1, c2, c3 = st.columns(3)
c1.metric("Mean", f"{mean:.4f}")
c2.metric("Median", f"{dataframe[column].median():.4f}")
c3.metric("Std Dev", f"{std_dev:.4f}")
st.markdown("-----------")
## KDE And Distribution Plot
st.subheader("KDE and Distribution plot")
if st.button("Calculate the Skew and KDE Plot"):
figure, skew, verdict = calculate_skew_and_plot_kdeplot(dataframe=dataframe,column= column)
st.write(f"Skew Value: {skew:.4f}")
st.subheader("VERDICT: {}".format(verdict))
st.pyplot(figure) # <---- Return the figure from the function calculate_skew_and_plot_kdeplot
plt.close(figure)
st.markdown("----------------------------------------------------")
# Outlier Detection
st.subheader("📌 Outlier Detection")
if st.button("Detect Outlier"):
st.session_state.detected = True
if st.session_state.get("detected", False):
skew = dataframe[column].skew()
q1, q2, q3, iqr, lower_bound, upper_bound, new_df = outlier_detection(dataframe, column, skew, mean, std_dev)
if q1 == 0.0 and iqr == 0.0:
st.info("💡 Normal distribution detected. Outliers calculated using **Z-Score Method (3 Std Dev)**.")
c1, c2 = st.columns(2)
c1.metric("Lower Bound", f"{lower_bound:.4f}")
c2.metric("Upper Bound", f"{upper_bound:.4f}")
else:
c11, c12, c13 = st.columns(3)
c21, c22, c23 = st.columns(3)
c11.metric("Q1", f"{q1:.4f}")
c12.metric("Q2", f"{q2:.4f}")
c13.metric("Q3", f"{q3:.4f}")
c21.metric("IQR", f"{iqr:.4f}")
c22.metric("Lower Bound", f"{lower_bound:.4f}")
c23.metric("Upper Bound", f"{upper_bound:.4f}")
if st.checkbox("View Updated Dataframe"):
st.title("Updated DataFrame")
st.dataframe(new_df)
st.markdown("---------")
# Missing Value Analysis
st.subheader("📌 Missing Value Analysis")
null_value,null_value_percentage, message = missing_value_calculation(dataframe, column)
mc1, mc2, mc3 = st.columns(3)
mc1.metric("Null Value", null_value)
mc2.metric("Null Value Percentage", null_value_percentage)
mc3.metric("Verdict", message)
# Missing Value Imputation
st.title("Data Cleaning Dashboard")
# Step 1: Check for missing values dynamically
missing_count = dataframe[column].isna().sum()
if missing_count > 0:
# Inform the user beautifully
st.warning(f"⚠️ '{column}' has {missing_count} missing values.")
# Capture the user's decision using a radio toggle
choice = st.radio(
"Do you wish to impute these Missing Values?",
options=["No", "Yes"],
index=0 # Defaults to "No"
)
Imputation_Methods = ["--Select--","Drop","Mean","Median","Mode","Constant","Missing_Category"]
selected_methods = st.selectbox("Select imputation Methods", Imputation_Methods)
if st.button("Apply Decision"):
if choice == "No":
st.info("Imputation is skipped by the user")
elif selected_methods == "--Select--":
st.info("Please Select an Imputation Method First")
else:
status = missing_value_treatment(dataframe, column, selected_methods)
st.success(f"✅ {status}")
else:
st.success(f"✅ '{column}' is perfectly clean! No missing values found.")
elif dataframe[column].dtype in categorical_dtype:
st.markdown("Categorical Data Type")
# Basic Description
st.subheader("Basic Description")
unique_count, mode, value_counts = counting_information(dataframe, column)
c1, c2,c3 = st.columns(3)
c1.metric("Unqiue Values", f"{unique_count}")
c3.metric("Mode", f"{value_counts[0]}")
c2.metric("Mode Value", f"{value_counts.index[0]}")
st.dataframe(value_counts.to_frame(), use_container_width= True)
st.markdown("-----------")
# Plotting Countplot
st.subheader("Distribution of Column")
graph = plot_countplot(dataframe, column)
if graph:
st.pyplot(graph)