LeonceNsh commited on
Commit
75a7b9a
·
verified ·
1 Parent(s): 9deed8b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +14 -223
app.py CHANGED
@@ -1,207 +1,3 @@
1
- import pandas as pd
2
- import networkx as nx
3
- import plotly.graph_objects as go
4
- from io import BytesIO
5
- from PIL import Image
6
- import gradio as gr
7
- import logging
8
-
9
- # Set up logging
10
- logging.basicConfig(level=logging.INFO)
11
- logger = logging.getLogger(__name__)
12
-
13
- # Load and preprocess the dataset
14
- file_path = "cbinsights_data.csv" # Replace with your actual file path
15
-
16
- try:
17
- data = pd.read_csv(file_path, skiprows=1)
18
- logger.info("CSV file loaded successfully.")
19
- except FileNotFoundError:
20
- logger.error(f"File not found: {file_path}")
21
- raise
22
- except Exception as e:
23
- logger.error(f"Error loading CSV file: {e}")
24
- raise
25
-
26
- # Standardize column names: strip whitespace and convert to lowercase
27
- data.columns = data.columns.str.strip().str.lower()
28
- logger.info(f"Standardized Column Names: {data.columns.tolist()}")
29
-
30
- # Identify the valuation column dynamically
31
- valuation_columns = [col for col in data.columns if 'valuation' in col.lower()]
32
- if not valuation_columns:
33
- logger.error("No column containing 'Valuation' found in the dataset.")
34
- raise ValueError("Data Error: Unable to find the valuation column. Please check your CSV file.")
35
- elif len(valuation_columns) > 1:
36
- logger.error("Multiple columns containing 'Valuation' found in the dataset.")
37
- raise ValueError("Data Error: Multiple valuation columns detected. Please ensure only one valuation column exists.")
38
- else:
39
- valuation_column = valuation_columns[0]
40
- logger.info(f"Using valuation column: {valuation_column}")
41
-
42
- # Clean and prepare data
43
- data["valuation_billions"] = data[valuation_column].replace({'\$': '', ',': ''}, regex=True)
44
- data["valuation_billions"] = pd.to_numeric(data["valuation_billions"], errors='coerce')
45
- logger.info("Valuation data cleaned and converted to numeric.")
46
-
47
- # Strip whitespace from all string columns
48
- data = data.apply(lambda col: col.str.strip() if col.dtype == "object" else col)
49
- logger.info("Whitespace stripped from all string columns.")
50
-
51
- # Rename columns for consistency
52
- expected_columns = {
53
- "company": "Company",
54
- "valuation_billions": "Valuation_Billions",
55
- "date_joined": "Date_Joined",
56
- "country": "Country",
57
- "city": "City",
58
- "industry": "Industry",
59
- "select_investors": "Select_Investors"
60
- }
61
-
62
- missing_columns = set(expected_columns.keys()) - set(data.columns)
63
- if missing_columns:
64
- logger.error(f"Missing columns in the dataset: {missing_columns}")
65
- raise ValueError(f"Data Error: Missing columns {missing_columns} in the dataset.")
66
-
67
- data = data.rename(columns=expected_columns)
68
- logger.info("Columns renamed for consistency.")
69
-
70
- # Parse the "Select_Investors" column to map investors to companies
71
- def build_investor_company_mapping(df):
72
- mapping = {}
73
- for _, row in df.iterrows():
74
- company = row["Company"]
75
- investors = row["Select_Investors"]
76
- if pd.notnull(investors):
77
- for investor in investors.split(","):
78
- investor = investor.strip()
79
- if investor: # Ensure investor is not an empty string
80
- mapping.setdefault(investor, []).append(company)
81
- return mapping
82
-
83
- investor_company_mapping = build_investor_company_mapping(data)
84
- logger.info("Investor to company mapping created.")
85
-
86
- # Function to filter investors based on selected country and industry
87
- def filter_investors_by_country_and_industry(selected_country, selected_industry):
88
- filtered_data = data.copy()
89
- logger.info(f"Filtering data for Country: {selected_country}, Industry: {selected_industry}")
90
-
91
- if selected_country != "All":
92
- filtered_data = filtered_data[filtered_data["Country"] == selected_country]
93
- logger.info(f"Data filtered by country: {selected_country}. Remaining records: {len(filtered_data)}")
94
- if selected_industry != "All":
95
- filtered_data = filtered_data[filtered_data["Industry"] == selected_industry]
96
- logger.info(f"Data filtered by industry: {selected_industry}. Remaining records: {len(filtered_data)}")
97
-
98
- investor_company_mapping_filtered = build_investor_company_mapping(filtered_data)
99
-
100
- # Calculate total valuation per investor
101
- investor_valuations = {}
102
- for investor, companies in investor_company_mapping_filtered.items():
103
- total_valuation = filtered_data[filtered_data["Company"].isin(companies)]["Valuation_Billions"].sum()
104
- if total_valuation >= 20: # Investors with >= 20B total valuation
105
- investor_valuations[investor] = total_valuation
106
-
107
- logger.info(f"Filtered investors with total valuation >= 20B: {len(investor_valuations)}")
108
-
109
- return list(investor_valuations.keys()), filtered_data
110
-
111
- # Function to generate the Plotly graph
112
- def generate_graph(selected_investors, filtered_data):
113
- if not selected_investors:
114
- logger.warning("No investors selected. Returning empty figure.")
115
- return go.Figure()
116
-
117
- investor_company_mapping_filtered = build_investor_company_mapping(filtered_data)
118
- filtered_mapping = {inv: investor_company_mapping_filtered[inv] for inv in selected_investors if inv in investor_company_mapping_filtered}
119
-
120
- logger.info(f"Generating graph for {len(filtered_mapping)} investors.")
121
-
122
- # Build the graph
123
- G = nx.Graph()
124
- for investor, companies in filtered_mapping.items():
125
- for company in companies:
126
- G.add_edge(investor, company)
127
-
128
- # Generate positions using spring layout
129
- pos = nx.spring_layout(G, k=0.2, seed=42)
130
-
131
- # Prepare Plotly traces
132
- edge_x = []
133
- edge_y = []
134
- for edge in G.edges():
135
- x0, y0 = pos[edge[0]]
136
- x1, y1 = pos[edge[1]]
137
- edge_x += [x0, x1, None]
138
- edge_y += [y0, y1, None]
139
-
140
- edge_trace = go.Scatter(
141
- x=edge_x, y=edge_y,
142
- line=dict(width=0.5, color='#888'),
143
- hoverinfo='none',
144
- mode='lines'
145
- )
146
-
147
- node_x = []
148
- node_y = []
149
- node_text = []
150
- node_size = []
151
- node_color = []
152
- customdata = []
153
- for node in G.nodes():
154
- x, y = pos[node]
155
- node_x.append(x)
156
- node_y.append(y)
157
- if node in filtered_mapping:
158
- node_text.append(f"Investor: {node}")
159
- node_size.append(20) # Investors have larger size
160
- node_color.append('orange')
161
- customdata.append(None) # Investors do not have a single valuation
162
- else:
163
- valuation = filtered_data.loc[filtered_data["Company"] == node, "Valuation_Billions"].sum()
164
- node_text.append(f"Company: {node}<br>Valuation: ${valuation}B")
165
- node_size.append(10 + (valuation / filtered_data["Valuation_Billions"].max()) * 30 if filtered_data["Valuation_Billions"].max() else 10)
166
- node_color.append('green')
167
- customdata.append(f"${valuation}B")
168
-
169
- node_trace = go.Scatter(
170
- x=node_x, y=node_y,
171
- mode='markers',
172
- hoverinfo='text',
173
- text=node_text,
174
- customdata=customdata,
175
- marker=dict(
176
- showscale=False,
177
- colorscale='YlGnBu',
178
- color=node_color,
179
- size=node_size,
180
- line_width=2
181
- )
182
- )
183
-
184
- fig = go.Figure(data=[edge_trace, node_trace],
185
- layout=go.Layout(
186
- title='Venture Network Visualization',
187
- titlefont_size=16,
188
- showlegend=False,
189
- hovermode='closest',
190
- margin=dict(b=20,l=5,r=5,t=40),
191
- annotations=[ dict(
192
- text="",
193
- showarrow=False,
194
- xref="paper", yref="paper") ],
195
- xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
196
- yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
197
- )
198
-
199
- fig.update_traces(marker=dict(line=dict(width=0.5, color='white')), selector=dict(mode='markers'))
200
-
201
- logger.info("Plotly graph generated successfully.")
202
-
203
- return fig
204
-
205
  # Gradio app function to update CheckboxGroup and filtered data
206
  def app(selected_country, selected_industry):
207
  investor_list, filtered_data = filter_investors_by_country_and_industry(selected_country, selected_industry)
@@ -219,14 +15,18 @@ def main():
219
  country_list = ["All"] + sorted(data["Country"].dropna().unique())
220
  industry_list = ["All"] + sorted(data["Industry"].dropna().unique())
221
 
 
 
 
 
222
  logger.info(f"Available countries: {country_list}")
223
  logger.info(f"Available industries: {industry_list}")
224
 
225
  with gr.Blocks() as demo:
226
  with gr.Row():
227
- # Set default value to "US" for country and "Enterprise Tech" for industry
228
- country_filter = gr.Dropdown(choices=country_list, label="Filter by Country", value="US")
229
- industry_filter = gr.Dropdown(choices=industry_list, label="Filter by Industry", value="Enterprise Tech")
230
 
231
  filtered_investor_list = gr.CheckboxGroup(choices=[], label="Select Investors", visible=False)
232
  graph_output = gr.Plot(label="Venture Network Graph")
@@ -254,26 +54,17 @@ def main():
254
  )
255
 
256
  # Handle plot click to display valuation
257
- def display_valuation(plotly_click):
258
- if plotly_click is None:
259
  return "Click on a company node to see its valuation."
260
- point = plotly_click
261
- if 'text' in point and point['text']:
262
- text = point['text']
263
- if "Company:" in text:
264
- # Extract valuation
265
- parts = text.split("<br>")
266
- company_part = parts[0]
267
- valuation_part = parts[1]
268
- company = company_part.replace("Company: ", "")
269
- valuation = valuation_part.replace("Valuation: ", "")
270
- return f"**{company}** has a valuation of **{valuation}**."
271
  return "Click on a company node to see its valuation."
272
 
273
- graph_output.event(
274
- "plotly_click",
275
  fn=display_valuation,
276
- inputs=graph_output,
277
  outputs=valuation_display
278
  )
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # Gradio app function to update CheckboxGroup and filtered data
2
  def app(selected_country, selected_industry):
3
  investor_list, filtered_data = filter_investors_by_country_and_industry(selected_country, selected_industry)
 
15
  country_list = ["All"] + sorted(data["Country"].dropna().unique())
16
  industry_list = ["All"] + sorted(data["Industry"].dropna().unique())
17
 
18
+ # Ensure the default values for dropdowns exist
19
+ default_country = "United States" if "United States" in country_list else "All"
20
+ default_industry = "Enterprise Tech" if "Enterprise Tech" in industry_list else "All"
21
+
22
  logger.info(f"Available countries: {country_list}")
23
  logger.info(f"Available industries: {industry_list}")
24
 
25
  with gr.Blocks() as demo:
26
  with gr.Row():
27
+ # Set default value for country and industry dropdowns
28
+ country_filter = gr.Dropdown(choices=country_list, label="Filter by Country", value=default_country)
29
+ industry_filter = gr.Dropdown(choices=industry_list, label="Filter by Industry", value=default_industry)
30
 
31
  filtered_investor_list = gr.CheckboxGroup(choices=[], label="Select Investors", visible=False)
32
  graph_output = gr.Plot(label="Venture Network Graph")
 
54
  )
55
 
56
  # Handle plot click to display valuation
57
+ def display_valuation(plotly_event):
58
+ if not plotly_event or "points" not in plotly_event or not plotly_event["points"]:
59
  return "Click on a company node to see its valuation."
60
+ point_data = plotly_event["points"][0]
61
+ if "customdata" in point_data and point_data["customdata"]:
62
+ return f"**Valuation:** {point_data['customdata']}"
 
 
 
 
 
 
 
 
63
  return "Click on a company node to see its valuation."
64
 
65
+ graph_output.events().on_click(
 
66
  fn=display_valuation,
67
+ inputs=[graph_output],
68
  outputs=valuation_display
69
  )
70