I have some CSV which I want to see as a dashboard, so I can easily explore the data. - Create a dropzone where a user can drop his csv. Once drop, render a table + Interactive charts showing transaction trends, project type distributions, and geographic breakdowns transaction_id,date,project_type,project_id,seller,buyer,quantity,price_per_ton,total_value,standard,vintage_year,location TR-12493,2024-01-15,Reforestation,PRJ-4587,Carbon Forest Partners,GreenInvest Group,5000,12.50,62500.00,Gold Standard,2023,Brazil TR-12494,2024-01-17,Renewable Energy,PRJ-2839,SunPower Solutions,Eco Capital Fund,3200,9.75,31200.00,VCS,2023,India TR-12495,2024-01-21,Methane Capture,PRJ-6721,AgriTech Emissions,Climate Forward,2800,14.25,39900.00,CAR,2023,United States
To upload files, please first save the app
import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
from datetime import datetime
import io
def create_transaction_trends_chart(df):
"""Create transaction trends over time"""
df_copy = df.copy()
df_copy['date'] = pd.to_datetime(df_copy['date'])
df_copy['month'] = df_copy['date'].dt.to_period('M')
# Group by month and calculate metrics
monthly_stats = df_copy.groupby('month').agg({
'total_value': ['sum', 'count'],
'quantity': 'sum'
}).round(2)
monthly_stats.columns = ['Total_Value', 'Transaction_Count', 'Total_Quantity']
monthly_stats.index = monthly_stats.index.astype(str)
# Create subplots
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('Total Value Over Time', 'Transaction Count Over Time',
'Total Quantity Over Time', 'Average Price per Ton'),
specs=[[{"secondary_y": False}, {"secondary_y": False}],
[{"secondary_y": False}, {"secondary_y": False}]]
)
# Total Value
fig.add_trace(
go.Scatter(x=monthly_stats.index, y=monthly_stats['Total_Value'],
mode='lines+markers', name='Total Value',
line=dict(color='#1f77b4', width=3)),
row=1, col=1
)
# Transaction Count
fig.add_trace(
go.Scatter(x=monthly_stats.index, y=monthly_stats['Transaction_Count'],
mode='lines+markers', name='Transaction Count',
line=dict(color='#ff7f0e', width=3)),
row=1, col=2
)
# Total Quantity
fig.add_trace(
go.Scatter(x=monthly_stats.index, y=monthly_stats['Total_Quantity'],
mode='lines+markers', name='Total Quantity',
line=dict(color='#2ca02c', width=3)),
row=2, col=1
)
# Average Price per Ton
avg_price = df_copy.groupby('month')['price_per_ton'].mean().round(2)
avg_price.index = avg_price.index.astype(str)
fig.add_trace(
go.Scatter(x=avg_price.index, y=avg_price.values,
mode='lines+markers', name='Avg Price per Ton',
line=dict(color='#d62728', width=3)),
row=2, col=2
)
fig.update_layout(height=600, showlegend=False, title_text="Transaction Trends Over Time")
fig.update_xaxes(title_text="Month")
return fig
def create_project_type_charts(df):
"""Create project type distribution charts"""
project_stats = df.groupby('project_type').agg({
'total_value': 'sum',
'quantity': 'sum',
'transaction_id': 'count'
}).round(2)
fig = make_subplots(
rows=1, cols=3,
subplot_titles=('Value by Project Type', 'Quantity by Project Type', 'Transaction Count by Project Type'),
specs=[[{"type": "pie"}, {"type": "pie"}, {"type": "pie"}]]
)
# Value distribution
fig.add_trace(
go.Pie(labels=project_stats.index, values=project_stats['total_value'],
name="Value", hole=0.3),
row=1, col=1
)
# Quantity distribution
fig.add_trace(
go.Pie(labels=project_stats.index, values=project_stats['quantity'],
name="Quantity", hole=0.3),
row=1, col=2
)
# Transaction count distribution
fig.add_trace(
go.Pie(labels=project_stats.index, values=project_stats['transaction_id'],
name="Count", hole=0.3),
row=1, col=3
)
fig.update_layout(height=400, title_text="Project Type Distributions")
return fig
def create_geographic_charts(df):
"""Create geographic breakdown charts"""
geo_stats = df.groupby('location').agg({
'total_value': 'sum',
'quantity': 'sum',
'transaction_id': 'count',
'price_per_ton': 'mean'
}).round(2).sort_values('total_value', ascending=True)
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('Total Value by Location', 'Total Quantity by Location',
'Transaction Count by Location', 'Average Price by Location'),
specs=[[{"type": "bar"}, {"type": "bar"}],
[{"type": "bar"}, {"type": "bar"}]]
)
# Total Value
fig.add_trace(
go.Bar(x=geo_stats['total_value'], y=geo_stats.index,
orientation='h', name='Total Value',
marker_color='#1f77b4'),
row=1, col=1
)
# Total Quantity
fig.add_trace(
go.Bar(x=geo_stats['quantity'], y=geo_stats.index,
orientation='h', name='Total Quantity',
marker_color='#ff7f0e'),
row=1, col=2
)
# Transaction Count
fig.add_trace(
go.Bar(x=geo_stats['transaction_id'], y=geo_stats.index,
orientation='h', name='Transaction Count',
marker_color='#2ca02c'),
row=2, col=1
)
# Average Price
fig.add_trace(
go.Bar(x=geo_stats['price_per_ton'], y=geo_stats.index,
orientation='h', name='Average Price',
marker_color='#d62728'),
row=2, col=2
)
fig.update_layout(height=600, showlegend=False, title_text="Geographic Breakdown")
return fig
def create_summary_metrics(df):
"""Create summary metrics cards"""
total_transactions = len(df)
total_value = df['total_value'].sum()
total_quantity = df['quantity'].sum()
avg_price = df['price_per_ton'].mean()
unique_projects = df['project_id'].nunique()
unique_locations = df['location'].nunique()
col1, col2, col3, col4, col5, col6 = st.columns(6)
with col1:
st.metric("Total Transactions", f"{total_transactions:,}")
with col2:
st.metric("Total Value", f"${total_value:,.2f}")
with col3:
st.metric("Total Quantity", f"{total_quantity:,.0f} tons")
with col4:
st.metric("Avg Price/Ton", f"${avg_price:.2f}")
with col5:
st.metric("Unique Projects", f"{unique_projects}")
with col6:
st.metric("Unique Locations", f"{unique_locations}")
def main():
st.set_page_config(page_title="Carbon Credit Dashboard", layout="wide")
st.title("🌱 Carbon Credit Transaction Dashboard")
st.markdown("Upload your CSV file to explore carbon credit transaction data with interactive visualizations.")
# File upload
uploaded_file = st.file_uploader(
"Drop your CSV file here or click to browse",
type=['csv'],
help="Upload a CSV file containing carbon credit transaction data"
)
# Sample data for demonstration
sample_data = """transaction_id,date,project_type,project_id,seller,buyer,quantity,price_per_ton,total_value,standard,vintage_year,location
TR-12493,2024-01-15,Reforestation,PRJ-4587,Carbon Forest Partners,GreenInvest Group,5000,12.50,62500.00,Gold Standard,2023,Brazil
TR-12494,2024-01-17,Renewable Energy,PRJ-2839,SunPower Solutions,Eco Capital Fund,3200,9.75,31200.00,VCS,2023,India
TR-12495,2024-01-21,Methane Capture,PRJ-6721,AgriTech Emissions,Climate Forward,2800,14.25,39900.00,CAR,2023,United States
TR-12496,2024-02-03,Reforestation,PRJ-4588,Forest Carbon Inc,EcoFund Ltd,4500,13.00,58500.00,Gold Standard,2023,Peru
TR-12497,2024-02-08,Solar Energy,PRJ-2840,Clean Energy Co,Green Capital,2500,10.50,26250.00,VCS,2023,Morocco
TR-12498,2024-02-15,Wind Energy,PRJ-2841,WindTech Solutions,Climate Partners,3800,11.25,42750.00,VCS,2023,Mexico
TR-12499,2024-03-01,Reforestation,PRJ-4589,Carbon Trees Ltd,Nature Investors,5200,12.75,66300.00,Gold Standard,2023,Indonesia
TR-12500,2024-03-10,Methane Capture,PRJ-6722,Farm Emissions Inc,Eco Solutions,3100,14.50,44950.00,CAR,2023,Brazil
TR-12501,2024-03-18,Solar Energy,PRJ-2842,SolarTech Corp,Green Future Fund,2900,10.25,29725.00,VCS,2023,Chile
TR-12502,2024-04-05,Reforestation,PRJ-4590,Amazon Carbon,Climate Capital,4800,13.25,63600.00,Gold Standard,2023,Colombia"""
if uploaded_file is None:
st.info("👆 Upload a CSV file to get started, or view the demo with sample data below.")
if st.button("Load Sample Data", type="primary"):
df = pd.read_csv(io.StringIO(sample_data))
st.session_state['data'] = df
else:
try:
df = pd.read_csv(uploaded_file)
st.session_state['data'] = df
st.success(f"✅ Successfully loaded {len(df)} transactions!")
except Exception as e:
st.error(f"Error reading CSV file: {str(e)}")
return
# Display dashboard if data is available
if 'data' in st.session_state:
df = st.session_state['data']
# Validate required columns
required_columns = ['date', 'project_type', 'quantity', 'price_per_ton', 'total_value', 'location']
missing_columns = [col for col in required_columns if col not in df.columns]
if missing_columns:
st.error(f"Missing required columns: {', '.join(missing_columns)}")
st.info("Required columns: " + ", ".join(required_columns))
return
# Data overview
st.markdown("---")
st.subheader("📊 Overview")
create_summary_metrics(df)
# Data table
st.markdown("---")
st.subheader("📋 Transaction Data")
with st.expander("View Raw Data", expanded=False):
st.dataframe(df, use_container_width=True)
# Charts
st.markdown("---")
st.subheader("📈 Transaction Trends")
try:
trends_chart = create_transaction_trends_chart(df)
st.plotly_chart(trends_chart, use_container_width=True)
except Exception as e:
st.error(f"Error creating trends chart: {str(e)}")
st.markdown("---")
st.subheader("🏗️ Project Type Analysis")
try:
project_chart = create_project_type_charts(df)
st.plotly_chart(project_chart, use_container_width=True)
except Exception as e:
st.error(f"Error creating project type charts: {str(e)}")
st.markdown("---")
st.subheader("🌍 Geographic Breakdown")
try:
geo_chart = create_geographic_charts(df)
st.plotly_chart(geo_chart, use_container_width=True)
except Exception as e:
st.error(f"Error creating geographic charts: {str(e)}")
# Additional analysis
st.markdown("---")
st.subheader("🔍 Detailed Analysis")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Top Sellers by Value**")
if 'seller' in df.columns:
top_sellers = df.groupby('seller')['total_value'].sum().sort_values(ascending=False).head(5)
st.dataframe(top_sellers.reset_index())
with col2:
st.markdown("**Top Buyers by Quantity**")
if 'buyer' in df.columns:
top_buyers = df.groupby('buyer')['quantity'].sum().sort_values(ascending=False).head(5)
st.dataframe(top_buyers.reset_index())
if __name__ == "__main__":
main()
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?