networkx-saas / app.py
LeonceNsh's picture
Update app.py
970f3bc verified
raw
history blame
7.76 kB
import pandas as pd
import networkx as nx
import plotly.graph_objects as go
import gradio as gr
import logging
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Load and preprocess the dataset
file_path = "cbinsights_data.csv" # Replace with your actual file path
try:
data = pd.read_csv(file_path, skiprows=1)
logger.info("CSV file loaded successfully.")
except FileNotFoundError:
logger.error(f"File not found: {file_path}")
raise
except Exception as e:
logger.error(f"Error loading CSV file: {e}")
raise
# Standardize column names: strip whitespace and convert to lowercase
data.columns = data.columns.str.strip().str.lower()
logger.info(f"Standardized Column Names: {data.columns.tolist()}")
# Identify the valuation column dynamically
valuation_columns = [col for col in data.columns if 'valuation' in col.lower()]
if not valuation_columns:
logger.error("No column containing 'Valuation' found in the dataset.")
raise ValueError("Data Error: Unable to find the valuation column. Please check your CSV file.")
elif len(valuation_columns) > 1:
logger.error("Multiple columns containing 'Valuation' found in the dataset.")
raise ValueError("Data Error: Multiple valuation columns detected. Please ensure only one valuation column exists.")
else:
valuation_column = valuation_columns[0]
logger.info(f"Using valuation column: {valuation_column}")
# Clean and prepare data
data["valuation_billions"] = data[valuation_column].replace({'\$': '', ',': ''}, regex=True)
data["valuation_billions"] = pd.to_numeric(data["valuation_billions"], errors='coerce')
logger.info("Valuation data cleaned and converted to numeric.")
# Strip whitespace from all string columns
data = data.apply(lambda col: col.str.strip() if col.dtype == "object" else col)
logger.info("Whitespace stripped from all string columns.")
# Rename columns for consistency
expected_columns = {
"company": "Company",
"valuation_billions": "Valuation_Billions",
"date_joined": "Date_Joined",
"country": "Country",
"city": "City",
"industry": "Industry",
"select_investors": "Select_Investors"
}
missing_columns = set(expected_columns.keys()) - set(data.columns)
if missing_columns:
logger.error(f"Missing columns in the dataset: {missing_columns}")
raise ValueError(f"Data Error: Missing columns {missing_columns} in the dataset.")
data = data.rename(columns=expected_columns)
logger.info("Columns renamed for consistency.")
# Parse the "Select_Investors" column to map investors to companies
def build_investor_company_mapping(df):
mapping = {}
for _, row in df.iterrows():
company = row["Company"]
investors = row["Select_Investors"]
if pd.notnull(investors):
for investor in investors.split(","):
investor = investor.strip()
if investor: # Ensure investor is not an empty string
mapping.setdefault(investor, []).append(company)
return mapping
investor_company_mapping = build_investor_company_mapping(data)
logger.info("Investor to company mapping created.")
# Function to filter investors based on selected country and industry
def filter_investors_by_country_and_industry(selected_country, selected_industry, valuation_threshold):
filtered_data = data.copy()
logger.info(f"Filtering data for Country: {selected_country}, Industry: {selected_industry}")
if selected_country != "All":
filtered_data = filtered_data[filtered_data["Country"] == selected_country]
logger.info(f"Data filtered by country: {selected_country}. Remaining records: {len(filtered_data)}")
if selected_industry != "All":
filtered_data = filtered_data[filtered_data["Industry"] == selected_industry]
logger.info(f"Data filtered by industry: {selected_industry}. Remaining records: {len(filtered_data)}")
investor_company_mapping_filtered = build_investor_company_mapping(filtered_data)
# Calculate total valuation per investor
investor_valuations = {}
for investor, companies in investor_company_mapping_filtered.items():
total_valuation = filtered_data[filtered_data["Company"].isin(companies)]["Valuation_Billions"].sum()
if total_valuation >= valuation_threshold:
investor_valuations[investor] = total_valuation
logger.info(f"Filtered investors with total valuation >= {valuation_threshold}B: {len(investor_valuations)}")
return list(investor_valuations.keys()), filtered_data
# Function to generate the Plotly graph
def generate_graph(investor_list, filtered_data):
if not investor_list:
logger.warning("No investors selected. Returning empty figure.")
return go.Figure()
G = nx.Graph()
for investor in investor_list:
companies = filtered_data[filtered_data["Select_Investors"].str.contains(investor, na=False)]["Company"].tolist()
for company in companies:
G.add_edge(investor, company)
pos = nx.spring_layout(G, k=0.2, seed=42)
# Create Plotly traces for edges and nodes
edge_trace = go.Scatter(
x=[],
y=[],
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines'
)
for edge in G.edges():
x0, y0 = pos[edge[0]]
x1, y1 = pos[edge[1]]
edge_trace['x'] += [x0, x1, None]
edge_trace['y'] += [y0, y1, None]
node_trace = go.Scatter(
x=[],
y=[],
text=[],
mode='markers',
hoverinfo='text',
marker=dict(
showscale=True,
colorscale='YlGnBu',
size=10,
colorbar=dict(thickness=15, title='Node Valuation')
)
)
for node in G.nodes():
x, y = pos[node]
node_trace['x'] += [x]
node_trace['y'] += [y]
node_trace['text'] += [f"{node}"]
fig = go.Figure(data=[edge_trace, node_trace])
return fig
# Gradio app function
def app(selected_country, selected_industry, valuation_threshold):
investor_list, filtered_data = filter_investors_by_country_and_industry(selected_country, selected_industry, valuation_threshold)
graph = generate_graph(investor_list, filtered_data)
return investor_list, graph
# Gradio Interface
def main():
country_list = ["All"] + sorted(data["Country"].dropna().unique())
industry_list = ["All"] + sorted(data["Industry"].dropna().unique())
logger.info(f"Available countries: {country_list}")
logger.info(f"Available industries: {industry_list}")
with gr.Blocks() as demo:
with gr.Row():
country_filter = gr.Dropdown(choices=country_list, label="Filter by Country", value="All")
industry_filter = gr.Dropdown(choices=industry_list, label="Filter by Industry", value="All")
valuation_threshold = gr.Slider(minimum=0, maximum=50, step=1, value=20, label="Valuation Threshold (in B)")
investor_output = gr.Text(label="Investor Results")
graph_output = gr.Plot(label="Venture Network Graph")
country_filter.change(
app,
inputs=[country_filter, industry_filter, valuation_threshold],
outputs=[investor_output, graph_output]
)
industry_filter.change(
app,
inputs=[country_filter, industry_filter, valuation_threshold],
outputs=[investor_output, graph_output]
)
valuation_threshold.change(
app,
inputs=[country_filter, industry_filter, valuation_threshold],
outputs=[investor_output, graph_output]
)
demo.launch()
if __name__ == "__main__":
main()