Spaces:
Running
Running
import streamlit as st | |
import pandas as pd | |
import numpy as np | |
import datetime | |
import plotly.express as px | |
import plotly.graph_objects as go | |
import statsmodels.api as sm | |
from millify import millify | |
from sklearn.linear_model import LinearRegression | |
from sklearn.metrics import r2_score | |
from st_aggrid import AgGrid | |
import io | |
import openpyxl | |
#from st_pages import Page, show_pages, add_page_title | |
# Set page title | |
st.set_page_config(page_title="Followers - Tiktok Analytics Dashboard", page_icon = "📊", layout = "centered", initial_sidebar_state = "auto") | |
st.header("Followers") | |
st.markdown("""Upload your files here to load your data! | |
*'Follower activity', 'Top territories', 'Gender', 'Total followers' (xlsx or csv format)* | |
""") | |
uploaded_files = st.file_uploader( | |
"Choose CSV or Excel files to upload", | |
accept_multiple_files=True, | |
type=['csv', 'xlsx']) | |
if uploaded_files: | |
data_list = [] | |
# read the file | |
with st.expander("View uploaded data"): | |
for uploaded_file in uploaded_files: | |
st.write("▾ Filename:", uploaded_file.name) | |
bytes_data = uploaded_file.read() | |
data = None | |
if uploaded_file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': | |
data = pd.read_excel(io.BytesIO(bytes_data)) | |
AgGrid(data) | |
else: | |
data = pd.read_csv(io.StringIO(bytes_data.decode('utf-8'))) | |
AgGrid(data) | |
data_list.append(data) | |
tab1, tab2, tab3, tab4, tab5 = st.tabs(["Follower Activity", "Gender", "Top Territories", "Followers", "Difference in Daily Followers"]) | |
for data in data_list: | |
#st.write(data.columns) | |
#st.write(data) | |
with tab1: | |
if 'Active followers' in data.columns: | |
# create a list of all unique dates in the data | |
unique_dates = data['Date'].unique() | |
# Add a date filter widget | |
filter_type = st.sidebar.radio("Select filter type for Follower Activity", ["Individual date", "Total date range"]) | |
if filter_type == "Individual date": | |
selected_date = st.sidebar.selectbox("Select a date", unique_dates) | |
# Filter the data to only include the selected date | |
filtered_data = data[data['Date'] == selected_date] | |
# Calculate the average number of followers for the selected date | |
avg_followers = filtered_data['Active followers'].mean() | |
elif filter_type == "Total date range": | |
# Filter the data to include the entire date range | |
filtered_data = data | |
# Calculate the average number of followers for the entire date range | |
avg_followers = filtered_data['Active followers'].mean() | |
#else: | |
# Get the start and end dates using st.date_input | |
#start_date = st.sidebar.date_input("Select start date", data['Date'].min(), data['Date'].max()) | |
#end_date = st.sidebar.date_input("Select end date", data['Date'].min(), data['Date'].max()) | |
# Filter the data based on the start and end dates | |
#filtered_data = data[(data['Date'] >= start_date) & (data['Date'] <= end_date)] | |
# create a datetime column from the date and hour columns | |
filtered_data['Datetime'] = pd.to_datetime(filtered_data['Date'] + ' ' + (filtered_data['Hour'] - 1).astype(str) + ':00:00') | |
# group the data by the datetime column and calculate the sum of active followers | |
grouped_data = filtered_data.groupby("Datetime")["Active followers"].sum().reset_index() | |
# create a line chart using Plotly Express | |
fig = px.line(filtered_data, x="Datetime", y="Active followers", title="Follower Activity") | |
# Add average line | |
fig.add_shape(type='line', x0=filtered_data['Datetime'].min(), y0=avg_followers, x1=filtered_data['Datetime'].max(), y1=avg_followers, line=dict(color='red', width=3, dash='dash')) | |
# Annotate average value onto average line | |
fig.add_annotation(x=filtered_data['Datetime'].max(), y=avg_followers, text=f"Average: {avg_followers:.0f}", showarrow=True, arrowhead=2) | |
st.plotly_chart(fig) | |
with tab2: | |
if 'Gender' in data.columns: | |
#st.write("Pie chart for 'Gender'") | |
gender_data = data.groupby('Gender')['Distribution'].apply(lambda x: pd.to_numeric(x.str.replace('%', ''), errors='coerce').dropna().mean()).reset_index() | |
fig = px.pie(gender_data, values='Distribution', names='Gender', title='Gender Distribution (%)', | |
color_discrete_sequence=['#1f77b4', '#ff7f0e']) | |
st.plotly_chart(fig) | |
with tab3: | |
if 'Top territories' in data.columns: | |
territories_data = data.groupby('Top territories')['Distribution'].apply(lambda x: pd.to_numeric(x.str.replace('%', ''), errors='coerce').dropna().mean()).reset_index() | |
territories_data = territories_data.sort_values(by='Distribution', ascending=True) | |
#st.write("Top 5 territories by distribution") | |
fig = px.bar(territories_data, x='Distribution', y='Top territories', title='Distribution (%) of Top 5 Countries', | |
color_discrete_sequence=px.colors.qualitative.Dark2) | |
st.plotly_chart(fig) | |
with tab4: | |
if 'Followers' in data.columns: | |
fig = px.line(data, x="Date", y="Followers", title="Total Followers", markers=True, | |
hover_data={'Followers': ':.2f'}) | |
st.plotly_chart(fig) | |
with tab5: | |
if 'Difference in followers from previous day' in data.columns: | |
# Create a custom color scale | |
def custom_color_scale(val): | |
if val >= 0: | |
return 'rgba(54, 164, 235, 0.8)' | |
else: | |
return 'rgba(255, 77, 77, 0.8)' | |
fig = px.bar(data, x="Date", y="Difference in followers from previous day", title="Difference in Daily Followers", | |
text='Difference in followers from previous day', color='Difference in followers from previous day', | |
hover_data={'Difference in followers from previous day': ':.2f'}, color_discrete_map={val: custom_color_scale(val) for val in data['Difference in followers from previous day']}) | |
# Customize the layout | |
fig.update_layout( | |
title="Difference in Daily Followers", | |
xaxis_title="Date", | |
yaxis_title="Difference in Daily Followers", | |
showlegend=False, | |
plot_bgcolor="white", | |
yaxis=dict(zeroline=True, zerolinewidth=2, zerolinecolor="black"), # Add a line at y=0 | |
) | |
st.plotly_chart(fig) | |