import plotly.express as px
from dash import Dash, dcc, callback, Input, Output
import numpy as np
import pandas as pd
df = pd.read_csv("x-24-followers.csv")
# dff = df[df['Token'].isin(['Qeqe','Kabal','Pepe','Chad'])]
# Remove unwanted columns
data_new = df.drop(columns=['Avg Growth', 'CAGR'])
# Convert all community size columns to numeric
data_new = data_new.apply(lambda col: pd.to_numeric(col.str.replace(',', '', regex=True), errors='coerce')
if col.name != 'Token' and col.dtype == 'object' else col)
# Explicitly replace -1 values with np.nan to ensure they are treated as missing values for interpolation
data_new.replace(-1, np.nan, inplace=True)
data_new['Token'] = data_new['Token'].astype(str)
# Interpolate missing values linearly
data_new_interpolated = data_new.set_index('Token').T.interpolate(method='linear').T.reset_index()
# Melt the dataframe to long format for plotting
data_long = data_new_interpolated.melt(id_vars=['Token'], var_name='Date', value_name='Community_Size')
# Convert the 'Community_Size' column to numeric, removing commas if present
data_long['Community_Size'] = data_long['Community_Size'].astype(float)
# Convert 'Date' to datetime for better plotting
data_long['Date'] = pd.to_datetime(data_long['Date'])
data_long = data_long.sort_values(by=['Token', 'Date'])
# Calculate the daily percentage growth for each token
data_long['Daily_Growth_Percentage'] = data_long.groupby('Token')['Community_Size'].pct_change(fill_method=None) * 100
app = Dash()
app.layout = [
dcc.Dropdown(id='my-token',
options=[{'label':'all', 'value':'all'}]+[{'label':x, 'value':x} for x in sorted(data_new['Token'])],
value=['all'],
multi=True,
clearable=False),
dcc.Graph(id='line-graph'),
dcc.Markdown('Minimum age of community (days)'),
dcc.Input(id='my-days', type='number', value=9, min=1, max=50, step=1),
dcc.Graph(id='bar-graph'),
]
@callback(
Output('line-graph', 'figure'),
Input('my-token', 'value')
)
def update_graph(tokens):
if tokens == ['all']:
fig = px.line(data_long, x='Date', y='Daily_Growth_Percentage',
color='Token',
title="Daily Community Growth Percentage Over Time by Token",
height=750,
labels={
'Daily_Growth_Percentage': 'Daily Growth (%)',
'Date': 'Date'})
fig.update_traces(mode='lines+markers')
else:
data_long_filtered = data_long[data_long['Token'].isin(tokens)]
fig = px.line(data_long_filtered, x='Date', y='Daily_Growth_Percentage',
color='Token',
title="Daily Community Growth Percentage Over Time by Token",
height=750,
labels={
'Daily_Growth_Percentage': 'Daily Growth (%)',
'Date': 'Date'})
fig.update_traces(mode='lines+markers')
return fig
@callback(
Output('bar-graph', 'figure'),
Input('my-days', 'value')
)
def update_graph(min_days):
# Count non-NaN values for Community_Size grouped by Token
valid_counts = data_long.groupby('Token')['Community_Size'].apply(
lambda x: x.notna().sum())
# Filter out Tokens with fewer than x-days valid Community_Size entries
tokens_to_keep = valid_counts[valid_counts >= min_days].index
filtered_df = data_long[data_long['Token'].isin(tokens_to_keep)]
median_growth = filtered_df.groupby("Token")["Daily_Growth_Percentage"].median().reset_index()
median_growth.rename(columns={"Daily_Growth_Percentage": "median_prcnt_growth"}, inplace=True)
fig = px.bar(median_growth, x='Token', y='median_prcnt_growth', title='Median growth')
return fig