|
|
import gradio as gr |
|
|
import pandas as pd |
|
|
import plotly.express as px |
|
|
import io |
|
|
import requests |
|
|
|
|
|
df_global = pd.DataFrame() |
|
|
|
|
|
|
|
|
def load_data(file): |
|
|
try: |
|
|
if file is None: |
|
|
return pd.DataFrame() |
|
|
ext = file.name.split('.')[-1] |
|
|
if ext == 'csv': |
|
|
return pd.read_csv(file.name) |
|
|
elif ext in ['xls', 'xlsx']: |
|
|
return pd.read_excel(file.name) |
|
|
elif ext == 'json': |
|
|
return pd.read_json(file.name) |
|
|
except Exception as e: |
|
|
print("File load error:", e) |
|
|
return pd.DataFrame() |
|
|
|
|
|
|
|
|
def load_url(url): |
|
|
try: |
|
|
response = requests.get(url) |
|
|
response.raise_for_status() |
|
|
if url.endswith(".csv"): |
|
|
return pd.read_csv(io.StringIO(response.text)) |
|
|
elif url.endswith(".json"): |
|
|
return pd.read_json(io.StringIO(response.text)) |
|
|
elif url.endswith(".xlsx") or url.endswith(".xls"): |
|
|
return pd.read_excel(io.BytesIO(response.content)) |
|
|
except Exception as e: |
|
|
print("URL load error:", e) |
|
|
return pd.DataFrame() |
|
|
|
|
|
|
|
|
def process_inputs(file, url): |
|
|
global df_global |
|
|
df = load_url(url) if url else load_data(file) |
|
|
|
|
|
if df.empty: |
|
|
return pd.DataFrame(), gr.update(choices=[], value=None), gr.update(choices=[], value=None) |
|
|
|
|
|
df_global = df |
|
|
all_cols = list(df.columns) |
|
|
num_cols = list(df.select_dtypes(include="number").columns) |
|
|
|
|
|
default_x = all_cols[0] if all_cols else None |
|
|
default_y = num_cols[0] if num_cols else None |
|
|
|
|
|
return df.head(), gr.update(choices=all_cols, value=default_x), gr.update(choices=num_cols, value=default_y) |
|
|
|
|
|
|
|
|
def update_plot(chart_type, x, y): |
|
|
global df_global |
|
|
if df_global.empty: |
|
|
return None, "No data loaded." |
|
|
|
|
|
try: |
|
|
chart = None |
|
|
if chart_type == "Bar Chart": |
|
|
chart = px.bar(df_global, x=x, y=y) |
|
|
elif chart_type == "Line Chart": |
|
|
chart = px.line(df_global, x=x, y=y) |
|
|
elif chart_type == "Scatter Plot": |
|
|
chart = px.scatter(df_global, x=x, y=y) |
|
|
elif chart_type == "Pie Chart": |
|
|
chart = px.pie(df_global, names=x, values=y) |
|
|
elif chart_type == "Box Plot": |
|
|
chart = px.box(df_global, x=x, y=y) |
|
|
|
|
|
summary_text = f"Chart Type: {chart_type}\nX-axis: {x}\nY-axis: {y}\n" |
|
|
if y in df_global.columns: |
|
|
stats = df_global[y].describe() |
|
|
summary_text += "\n" + stats.to_string() |
|
|
|
|
|
return chart, summary_text |
|
|
except Exception as e: |
|
|
print("Plot error:", e) |
|
|
return None, f"Error: {str(e)}" |
|
|
|
|
|
|
|
|
with gr.Blocks(css=""" |
|
|
body { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
font-family: 'Segoe UI', sans-serif; |
|
|
background: #0f2027; |
|
|
background: linear-gradient(to right, #2c5364, #203a43, #0f2027); |
|
|
color: skyblue; |
|
|
} |
|
|
#bg-theme { |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
z-index: -2; |
|
|
background: linear-gradient(120deg, rgba(33,147,176,0.6), rgba(109,213,237,0.6)); |
|
|
background-size: 200% 200%; |
|
|
animation: bgMove 20s ease infinite; |
|
|
filter: blur(100px); |
|
|
} |
|
|
@keyframes bgMove { |
|
|
0% { background-position: 0% 50%; } |
|
|
50% { background-position: 100% 50%; } |
|
|
100% { background-position: 0% 50%; } |
|
|
} |
|
|
.fade-in { |
|
|
animation: fadeInUp 1s ease both; |
|
|
} |
|
|
@keyframes fadeInUp { |
|
|
0% { opacity: 0; transform: translateY(20px); } |
|
|
100% { opacity: 1; transform: translateY(0); } |
|
|
} |
|
|
""") as demo: |
|
|
|
|
|
gr.HTML('<div id="bg-theme"></div>') |
|
|
gr.Markdown( |
|
|
""" |
|
|
<h1 style=" |
|
|
font-size: 3.5em; |
|
|
background: linear-gradient(270deg, #00c9ff, #92fe9d, #ff6a00, #ffb6b9); |
|
|
background-size: 800% 800%; |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
animation: rainbow 8s ease infinite; |
|
|
font-weight: bold; |
|
|
"> |
|
|
⚡⚡☄️ Thunder BI-Data Visualizer |
|
|
</h1> |
|
|
<style> |
|
|
@keyframes rainbow { |
|
|
0%{background-position:0% 50%;} |
|
|
50%{background-position:100% 50%;} |
|
|
100%{background-position:0% 50%;} |
|
|
} |
|
|
</style> |
|
|
""", elem_classes="fade-in" |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
file_input = gr.File(file_types=[".csv", ".xlsx", ".json"], label="Upload File") |
|
|
url_input = gr.Textbox(label="Or enter file URL") |
|
|
|
|
|
df_preview = gr.Dataframe(label="Preview", interactive=False) |
|
|
x_dropdown = gr.Dropdown(label="X-axis") |
|
|
y_dropdown = gr.Dropdown(label="Y-axis") |
|
|
chart_type = gr.Dropdown(["Bar Chart", "Line Chart", "Scatter Plot", "Pie Chart", "Box Plot"], label="Chart Type") |
|
|
plot_area = gr.Plot(label="Chart") |
|
|
summary_box = gr.Textbox(label="Summary", lines=10) |
|
|
generate_button = gr.Button("Generate Plot") |
|
|
|
|
|
|
|
|
file_input.change(process_inputs, inputs=[file_input, url_input], outputs=[df_preview, x_dropdown, y_dropdown]) |
|
|
url_input.change(process_inputs, inputs=[file_input, url_input], outputs=[df_preview, x_dropdown, y_dropdown]) |
|
|
|
|
|
generate_button.click(update_plot, inputs=[chart_type, x_dropdown, y_dropdown], outputs=[plot_area, summary_box]) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|