harrychangjr commited on
Commit
64e353a
1 Parent(s): 13bb6d5

clone to hf

Browse files
Files changed (5) hide show
  1. app.py +69 -0
  2. pages/content.py +583 -0
  3. pages/followers.py +141 -0
  4. pages/overview.py +227 -0
  5. requirements.txt +15 -0
app.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ #from st_pages import Page, show_pages, add_page_title
3
+
4
+ ### Structure ###
5
+ # Streamlit file uploader to upload following files:
6
+ # Engagement - "Last 60 days.csv"
7
+ # Content - "Trending videos.csv", "Video Posts.csv"
8
+ # Followers - "Follower activity.csv", "Top territories.csv", "Gender.csv", "Total followers.csv"
9
+
10
+ # sidebar with 3 above-mentioned sections + overview + how-to guide
11
+
12
+ # for each section, try to replicate the respective dashboards + see if can add additional filters and sliders
13
+
14
+ # Optional -- adds the title and icon to the current page
15
+ # add_page_title()
16
+
17
+ # Set page title
18
+ st.set_page_config(page_title="Tiktok Analytics Dashboard", page_icon = "📊", layout = "centered", initial_sidebar_state = "auto")
19
+
20
+ st.header("Tiktok Analytics Dashboard")
21
+
22
+
23
+
24
+ def social_icons(width=24, height=24, **kwargs):
25
+ icon_template = '''
26
+ <a href="{url}" target="_blank" style="margin-right: 20px;">
27
+ <img src="{icon_src}" alt="{alt_text}" width="{width}" height="{height}">
28
+ </a>
29
+ '''
30
+
31
+ icons_html = ""
32
+ for name, url in kwargs.items():
33
+ icon_src = {
34
+ "youtube": "https://img.icons8.com/ios-filled/100/null/youtube-play.png",
35
+ "linkedin": "https://img.icons8.com/ios-filled/100/null/linkedin.png",
36
+ "github": "https://img.icons8.com/ios-filled/100/null/github--v2.png",
37
+ "wordpress": "https://img.icons8.com/ios-filled/100/null/wordpress--v1.png",
38
+ "email": "https://img.icons8.com/ios-filled/100/null/filled-message.png",
39
+ "website": "https://img.icons8.com/ios/100/null/domain--v1.png"
40
+ }.get(name.lower())
41
+
42
+ if icon_src:
43
+ icons_html += icon_template.format(url=url, icon_src=icon_src, alt_text=name.capitalize(), width=width, height=height)
44
+
45
+ return icons_html
46
+ st.subheader("So how do I use this?")
47
+ st.markdown("""
48
+ Designed to provide extra value to the existing dashboard available on TikTok Analytics, individual users or businesses can download the relevant csv/xlsx files before loading them
49
+ to this custom dashboard.
50
+
51
+ |Section|Description|Files required|
52
+ |--------|-----------|--------------|
53
+ |Overview| Number cards for video views, profile views, likes, comments and shares over past 60 days, with various plots for up to 3 variables at once | `Last 60 days` |
54
+ |Content| Analysis of trending videos over past 7 days, including investigating relationships between number of hashtags used and video views| `Trending videos` |
55
+ |Followers| Broad insights of follower activity by hour, as well as breakdown of demographics by country and gender| `Follower activity` `Top territories` `Gender` `Total followers` |
56
+
57
+
58
+ Dashboard will be updated as and whenever necessary. Enjoy!
59
+ """)
60
+ st.markdown("""""")
61
+ linkedin_url = "https://www.linkedin.com/in/harrychangjr/"
62
+ github_url = "https://github.com/harrychangjr"
63
+ email_url = "mailto:[email protected]"
64
+ website_url = "https://harrychangjr.streamlit.app"
65
+ st.markdown(
66
+ social_icons(32, 32, LinkedIn=linkedin_url, GitHub=github_url, Email=email_url, Website=website_url),
67
+ unsafe_allow_html=True)
68
+ st.markdown("")
69
+ st.markdown("*Copyright © 2023 Harry Chang*")
pages/content.py ADDED
@@ -0,0 +1,583 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import datetime
5
+ import plotly.express as px
6
+ import plotly.graph_objects as go
7
+ import statsmodels.api as sm
8
+ from millify import millify
9
+ from sklearn.linear_model import LinearRegression
10
+ from sklearn.metrics import r2_score
11
+ from st_aggrid import AgGrid
12
+ import io
13
+ import re
14
+ import emoji
15
+ from collections import Counter
16
+ import openpyxl
17
+ from gensim.models import Word2Vec
18
+ from sklearn.metrics.pairwise import cosine_similarity
19
+ from sklearn.linear_model import LinearRegression
20
+ from sklearn.ensemble import RandomForestRegressor
21
+ from xgboost import XGBRegressor
22
+ from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
23
+ from sklearn.model_selection import train_test_split
24
+ import seaborn as sns
25
+ import matplotlib.pyplot as plt
26
+ from mpl_toolkits.mplot3d import Axes3D
27
+
28
+ #from st_pages import Page, show_pages, add_page_title
29
+
30
+ # Set page title
31
+ st.set_page_config(page_title="Content - Tiktok Analytics Dashboard", page_icon = "📊", layout = "centered", initial_sidebar_state = "auto")
32
+
33
+ st.header("Content")
34
+ st.markdown("""Upload your files here to load your data!
35
+
36
+ *'Trending videos' (xlsx or csv format)*
37
+ """)
38
+
39
+ def plot_chart(data, chart_type, x_var, y_var, z_var=None, show_regression_line=False, show_r_squared=False):
40
+ scatter_marker_color = 'green'
41
+ regression_line_color = 'red'
42
+ if chart_type == "line":
43
+ fig = px.line(data, x=x_var, y=y_var)
44
+
45
+ elif chart_type == "bar":
46
+ fig = px.bar(data, x=x_var, y=y_var)
47
+
48
+ elif chart_type == "scatter":
49
+ fig = px.scatter(data, x=x_var, y=y_var, color_discrete_sequence=[scatter_marker_color])
50
+
51
+ if show_regression_line:
52
+ X = data[x_var].values.reshape(-1, 1)
53
+ y = data[y_var].values.reshape(-1, 1)
54
+ model = LinearRegression().fit(X, y)
55
+ y_pred = model.predict(X)
56
+ r_squared = r2_score(y, y_pred) # Calculate R-squared value
57
+
58
+ fig.add_trace(
59
+ go.Scatter(x=data[x_var], y=y_pred[:, 0], mode='lines', name='Regression Line', line=dict(color=regression_line_color))
60
+ )
61
+
62
+ # Add R-squared value as a text annotation
63
+ fig.add_annotation(
64
+ x=data[x_var].max(),
65
+ y=y_pred[-1, 0],
66
+ text=f"R-squared: {r_squared:.4f}",
67
+ showarrow=False,
68
+ font=dict(size=14),
69
+ bgcolor='rgba(255, 255, 255, 0.8)',
70
+ bordercolor='black',
71
+ borderwidth=1,
72
+ borderpad=4
73
+ )
74
+
75
+ elif chart_type == "heatmap":
76
+ fig = px.imshow(data, color_continuous_scale='Inferno')
77
+
78
+ elif chart_type == "scatter_3d":
79
+ if z_var is not None:
80
+ fig = px.scatter_3d(data, x=x_var, y=y_var, z=z_var, color=data.columns[0])
81
+ else:
82
+ st.warning("Please select Z variable for 3D line plot.")
83
+ return
84
+
85
+ elif chart_type == "line_3d":
86
+ if z_var is not None:
87
+ fig = go.Figure(data=[go.Scatter3d(x=data[x_var], y=data[y_var], z=data[z_var], mode='lines')])
88
+ fig.update_layout(scene=dict(xaxis_title=x_var, yaxis_title=y_var, zaxis_title=z_var)) # Set the axis name
89
+ else:
90
+ st.warning("Please select Z variable for 3D line plot.")
91
+ return
92
+
93
+ elif chart_type == "surface_3d":
94
+ if z_var is not None:
95
+ fig = go.Figure(data=[go.Surface(z=data.values)])
96
+ fig.update_layout(scene=dict(xaxis_title=x_var, yaxis_title=y_var, zaxis_title=z_var)) # Set the axis name
97
+ else:
98
+ st.warning("Please select Z variable for 3D line plot.")
99
+ return
100
+
101
+ elif chart_type == "radar":
102
+ fig = go.Figure()
103
+ for col in data.columns[1:]:
104
+ fig.add_trace(go.Scatterpolar(r=data[col], theta=data[x_var], mode='lines', name=col))
105
+ fig.update_layout(polar=dict(radialaxis=dict(visible=True, range=[data[data.columns[1:]].min().min(), data[data.columns[1:]].max().max()])))
106
+
107
+ st.plotly_chart(fig)
108
+
109
+ def plot_radar_chart(data, columns):
110
+ df = data[columns]
111
+ fig = go.Figure()
112
+
113
+ for i in range(len(df)):
114
+ date_label = data.loc[i, 'Date']
115
+ fig.add_trace(go.Scatterpolar(
116
+ r=df.loc[i].values,
117
+ theta=df.columns,
118
+ fill='toself',
119
+ name=date_label
120
+ ))
121
+
122
+ fig.update_layout(
123
+ polar=dict(
124
+ radialaxis=dict(
125
+ visible=True,
126
+ range=[0, df.max().max()]
127
+ )
128
+ ),
129
+ showlegend=True
130
+ )
131
+
132
+ st.plotly_chart(fig)
133
+
134
+ uploaded_files = st.file_uploader(
135
+ "Choose CSV or Excel files to upload",
136
+ accept_multiple_files=True,
137
+ type=['csv', 'xlsx'])
138
+
139
+ if uploaded_files:
140
+ data_list = []
141
+
142
+ # read the file
143
+ with st.expander("View uploaded data - data covered over 7-day period only"):
144
+ for uploaded_file in uploaded_files:
145
+ st.write("▾ Filename:", uploaded_file.name)
146
+ bytes_data = uploaded_file.read()
147
+ data = None
148
+ if uploaded_file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
149
+ data = pd.read_excel(io.BytesIO(bytes_data))
150
+ AgGrid(data)
151
+ else:
152
+ data = pd.read_csv(io.StringIO(bytes_data.decode('utf-8')))
153
+ AgGrid(data)
154
+
155
+ data_list.append(data)
156
+ #st.write(data_list)
157
+
158
+ #tab1, tab2 = st.tabs(["Trending Videos", "Video Posts"])
159
+ for data in data_list:
160
+ #st.write(data.columns)
161
+ #st.write(data)
162
+ #with tab1:
163
+ if 'video_view_within_days' in data.columns: #Trending Videos
164
+ # Extract hashtags using a regex pattern
165
+ def extract_hashtags(title):
166
+ return re.findall(r'#\w+', title)
167
+
168
+ # Extract emojis using the emoji library
169
+ #def extract_emojis(title):
170
+ #return [c for c in title if c in emoji.emojize(c)]
171
+
172
+ # Remove emojis and hashtags from the title
173
+ def clean_title(title):
174
+ #title_without_emojis = emoji.get_emoji_regexp().sub(u'', title)
175
+ title_without_hashtags = re.sub(r'#\w+', '', title)
176
+ return title_without_hashtags.strip()
177
+
178
+ data['Hashtags'] = data['Video title'].apply(extract_hashtags)
179
+ #data['Emojis'] = data['Video title'].apply(extract_emojis)
180
+ data['Cleaned_title'] = data['Video title'].apply(clean_title)
181
+ # Add a new column to store the hashtag count
182
+ data['Hashtag_count'] = data['Hashtags'].apply(len)
183
+ st.write(data)
184
+ options = ["Total views", "Total shares", "Total likes", "Total comments", "Number of Hashtags", "Hashtag Performance"]
185
+ selected_feature = st.selectbox(label="Select feature", options=options, index=0)
186
+ if selected_feature == "Total views":
187
+ data = data.sort_values(by='Total views', ascending=True)
188
+ fig = px.bar(data, x='Total views', y='Cleaned_title', title='Views of trending videos for the week',
189
+ color_discrete_sequence=px.colors.qualitative.Alphabet, hover_data={'Total views': ':.2f'})
190
+ st.plotly_chart(fig)
191
+ elif selected_feature == "Total shares":
192
+ data = data.sort_values(by='Total shares\xa0', ascending=True)
193
+ fig = px.bar(data, x='Total shares\xa0', y='Cleaned_title', title='Shares of trending videos for the week',
194
+ color_discrete_sequence=px.colors.qualitative.Set1, hover_data={'Total shares\xa0': ':.2f'})
195
+ st.plotly_chart(fig)
196
+ elif selected_feature == "Total likes":
197
+ data = data.sort_values(by='Total likes', ascending=True)
198
+ fig = px.bar(data, x='Total likes', y='Cleaned_title', title='Likes of trending videos for the week',
199
+ color_discrete_sequence=px.colors.qualitative.Antique, hover_data={'Total likes': ':.2f'})
200
+ st.plotly_chart(fig)
201
+ elif selected_feature == "Total comments":
202
+ data = data.sort_values(by='Total comments', ascending=True)
203
+ fig = px.bar(data, x='Total comments', y='Cleaned_title', title='Comments of trending videos for the week',
204
+ color_discrete_sequence=px.colors.qualitative.Vivid, hover_data={'Total comments': ':.2f'})
205
+ st.plotly_chart(fig)
206
+ elif selected_feature == "Number of Hashtags":
207
+ # Count the occurrences of each hashtag
208
+ hashtag_counts = Counter(hashtag for hashtags in data['Hashtags'] for hashtag in hashtags)
209
+
210
+ # Get the top N most common hashtags
211
+ N = 10
212
+ top_hashtags = hashtag_counts.most_common(N)
213
+
214
+ # Display the top hashtags
215
+ print(f"Top {N} hashtags:")
216
+ for hashtag, count in top_hashtags:
217
+ print(f"{hashtag}: {count}")
218
+
219
+ # Visualize the results with a Plotly bar chart
220
+ fig = go.Figure(go.Bar(
221
+ x=[t[0] for t in top_hashtags],
222
+ y=[t[1] for t in top_hashtags],
223
+ text=[t[1] for t in top_hashtags],
224
+ textposition='auto',
225
+ marker_color='rgba(58, 71, 80, 0.6)',
226
+ opacity=0.8
227
+ ))
228
+
229
+ fig.update_layout(
230
+ title=f'Top {N} Hashtags',
231
+ xaxis_title='Hashtags',
232
+ yaxis_title='Count',
233
+ xaxis_tickangle=-45
234
+ )
235
+
236
+ st.plotly_chart(fig)
237
+
238
+ tab1, tab2, tab3, tab4 = st.tabs(["vs Views", "vs Shares", "vs Likes", "vs Comments"])
239
+ with tab1:
240
+ fig = px.scatter(data, x='Hashtag_count', y='Total views', hover_data=['Cleaned_title'])
241
+ fig.update_layout(
242
+ title='Hashtag Count vs. Views',
243
+ xaxis_title='Hashtag Count',
244
+ yaxis_title='Views'
245
+ )
246
+ st.plotly_chart(fig)
247
+ with tab2:
248
+ fig = px.scatter(data, x='Hashtag_count', y='Total shares\xa0', hover_data=['Cleaned_title'])
249
+ fig.update_layout(
250
+ title='Hashtag Count vs. Shares',
251
+ xaxis_title='Hashtag Count',
252
+ yaxis_title='Shares'
253
+ )
254
+ st.plotly_chart(fig)
255
+ with tab3:
256
+ fig = px.scatter(data, x='Hashtag_count', y='Total likes', hover_data=['Cleaned_title'])
257
+ fig.update_layout(
258
+ title='Hashtag Count vs. Likes',
259
+ xaxis_title='Hashtag Count',
260
+ yaxis_title='Likes'
261
+ )
262
+ st.plotly_chart(fig)
263
+ with tab4:
264
+ fig = px.scatter(data, x='Hashtag_count', y='Total comments', hover_data=['Cleaned_title'])
265
+ fig.update_layout(
266
+ title='Hashtag Count vs. Comments',
267
+ xaxis_title='Hashtag Count',
268
+ yaxis_title='Comments'
269
+ )
270
+ st.plotly_chart(fig)
271
+ elif selected_feature == "Hashtag Performance":
272
+ # Tokenize hashtags and create a list of unique hashtags
273
+ tokenized_hashtags = data["Hashtags"].tolist()
274
+ unique_hashtags = list(set([tag for tags in tokenized_hashtags for tag in tags]))
275
+ # Train a word2vec model
276
+ model = Word2Vec(tokenized_hashtags, size=50, window=5, min_count=1, workers=4)
277
+
278
+ # Create a hashtag vector dictionary
279
+ hashtag_vectors = {tag: model.wv[tag] for tag in unique_hashtags}
280
+ st.subheader("Explaining the concept of hashtag performance scores and cosine similarity scores")
281
+ st.markdown(
282
+ """
283
+ So how are the **performance scores** calculated for each feature?
284
+
285
+ In each line, the code goes through each unique hashtag and selects all videos that use that hashtag. It then calculates the mean of the respective performance metric (views, shares, likes, or comments) for those videos.
286
+
287
+ This gives an average performance score for each hashtag, which can be used as an indication of how well videos with that hashtag tend to perform on average. However, this is a simplistic metric and there may be other factors influencing the performance of a video. It's also worth noting that the mean is sensitive to extreme values, so a few very popular or unpopular videos could skew the average performance for a given hashtag.
288
+ """)
289
+
290
+ st.markdown("""
291
+ How about **cosine similarity**?
292
+
293
+ Cosine similarity is a metric used to measure how similar two vectors are, irrespective of their size. In the context of Natural Language Processing (NLP), and in this case, it's used to measure the semantic similarity between two hashtags based on their embeddings (vectors) generated by the Word2Vec model.
294
+
295
+ In simple terms, it measures the cosine of the angle between two vectors. If the vectors are identical, the angle is 0, so the cosine is 1, indicating perfect similarity. If the vectors are orthogonal (i.e., the angle between them is 90 degrees), they're considered not similar, and the cosine similarity is 0. If the vectors point in opposite directions (i.e., the angle is 180 degrees), the cosine similarity is -1, indicating that they're diametrically dissimilar.
296
+ """)
297
+ # Calculate the average performance of each hashtag - views
298
+ hashtag_performance_views = {tag: data[data["Hashtags"].apply(lambda x: tag in x)]["Total views"].mean() for tag in unique_hashtags}
299
+
300
+ # Calculate the average performance of each hashtag - shares
301
+ hashtag_performance_shares = {tag: data[data["Hashtags"].apply(lambda x: tag in x)]["Total shares\xa0"].mean() for tag in unique_hashtags}
302
+
303
+ # Calculate the average performance of each hashtag - likes
304
+ hashtag_performance_likes = {tag: data[data["Hashtags"].apply(lambda x: tag in x)]["Total likes"].mean() for tag in unique_hashtags}
305
+
306
+ # Calculate the average performance of each hashtag - comments
307
+ hashtag_performance_comments = {tag: data[data["Hashtags"].apply(lambda x: tag in x)]["Total comments"].mean() for tag in unique_hashtags}
308
+
309
+ # Calculate the similarity between hashtags
310
+ similarity_matrix = cosine_similarity(list(hashtag_vectors.values()))
311
+
312
+ # Convert the similarity matrix into a DataFrame
313
+ similarity_df = pd.DataFrame(similarity_matrix, index=unique_hashtags, columns=unique_hashtags)
314
+
315
+ # Convert the performance dictionaries into DataFrames
316
+ perf_views_df = pd.DataFrame(list(hashtag_performance_views.items()), columns=["hashtag", "views"])
317
+ perf_shares_df = pd.DataFrame(list(hashtag_performance_shares.items()), columns=["hashtag", "shares"])
318
+ perf_likes_df = pd.DataFrame(list(hashtag_performance_likes.items()), columns=["hashtag", "likes"])
319
+ perf_comments_df = pd.DataFrame(list(hashtag_performance_comments.items()), columns=["hashtag", "comments"])
320
+
321
+ # Merge the performance DataFrames into a single DataFrame
322
+ perf_df = pd.merge(perf_views_df, perf_shares_df, on="hashtag")
323
+ perf_df = pd.merge(perf_df, perf_likes_df, on="hashtag")
324
+ perf_df = pd.merge(perf_df, perf_comments_df, on="hashtag")
325
+
326
+ # Convert the similarity matrix into a 1D series
327
+ similarity_series = similarity_df.unstack()
328
+
329
+ # Rename the series index
330
+ similarity_series.index.rename(["hashtag1", "hashtag2"], inplace=True)
331
+
332
+ # Convert the series into a DataFrame
333
+ similarity_df = similarity_series.to_frame("similarity").reset_index()
334
+
335
+ # Merge the similarity DataFrame with the performance DataFrame
336
+ merged_df = pd.merge(similarity_df, perf_df, left_on="hashtag1", right_on="hashtag")
337
+
338
+ # Calculate the correlation between hashtag similarity and performance
339
+ correlation = merged_df[["similarity", "views", "shares", "likes", "comments"]].corr()
340
+ st.subheader("Correlation matrix between hashtag cosine similarity values and performance values")
341
+ #st.write(correlation)
342
+ # Create a heatmap
343
+ plt.figure(figsize=(10, 8))
344
+ sns.heatmap(correlation, annot=True, fmt=".2f", cmap='coolwarm', cbar=True)
345
+
346
+ # Show the plot in Streamlit
347
+ st.pyplot(plt)
348
+ # Rename the 'value' columns to make them unique
349
+ df1 = pd.DataFrame(list(hashtag_performance_views.items()), columns=["hashtag", "value"])
350
+ df2 = pd.DataFrame(list(hashtag_performance_shares.items()), columns=["hashtag", "value"])
351
+ df3 = pd.DataFrame(list(hashtag_performance_likes.items()), columns=["hashtag", "value"])
352
+ df4 = pd.DataFrame(list(hashtag_performance_comments.items()), columns=["hashtag", "value"])
353
+
354
+ df1.rename(columns={'value': 'value_views'}, inplace=True)
355
+ df2.rename(columns={'value': 'value_shares'}, inplace=True)
356
+ df3.rename(columns={'value': 'value_likes'}, inplace=True)
357
+ df4.rename(columns={'value': 'value_comments'}, inplace=True)
358
+
359
+ # Merge the DataFrames on the 'hashtag' column
360
+ merged_df = df1.merge(df2, on='hashtag').merge(df3, on='hashtag').merge(df4, on='hashtag')
361
+
362
+ st.subheader("Hashtag Performance Scores based on Views, Shares, Likes and Comments - Calculated using average of all videos' metrics containing a particular hashtag")
363
+ st.write(merged_df)
364
+
365
+ # Create a pair plot with regression lines
366
+ st.write("**Pair Plots**")
367
+ sns.pairplot(merged_df, kind="reg", diag_kind="kde")
368
+ st.pyplot(plt)
369
+
370
+ # Split the data into train and test sets
371
+ X = merged_df[["value_shares", "value_likes", "value_comments"]]
372
+ y = merged_df["value_views"]
373
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
374
+
375
+ #st.write("**3D Scatterplot of Predictors with Regression Plane**")
376
+ # Create a 3D scatterplot with a regression plane
377
+ #fig = plt.figure()
378
+ #ax = fig.add_subplot(111, projection="3d")
379
+
380
+ #ax.scatter(merged_df["value_shares"], merged_df["value_likes"], merged_df["value_comments"], c="blue", marker="o")
381
+
382
+ # Create a meshgrid for the regression plane
383
+ #x_range = np.linspace(merged_df["value_shares"].min(), merged_df["value_shares"].max(), num=10)
384
+ #y_range = np.linspace(merged_df["value_likes"].min(), merged_df["value_likes"].max(), num=10)
385
+
386
+ #x_grid, y_grid = np.meshgrid(x_range, y_range)
387
+
388
+ # Calculate the regression plane
389
+ #X_grid = np.column_stack((x_grid.ravel(), y_grid.ravel()))
390
+ #plane = np.zeros(X_grid.shape[0])
391
+
392
+ #for i, (x, y) in enumerate(X_grid):
393
+ #plane[i] = model.predict(np.column_stack((x, y, merged_df["value_comments"].mean())).reshape(1, -1))
394
+
395
+ #z_grid = plane.reshape(x_grid.shape)
396
+
397
+ #ax.set_xlabel("value_shares")
398
+ #ax.set_ylabel("value_likes")
399
+ #ax.set_zlabel("value_comments")
400
+
401
+ #plt.show()
402
+ #st.pyplot(plt)
403
+
404
+ # Fit the models on the training data
405
+ lr_model = LinearRegression()
406
+ lr_model.fit(X_train, y_train)
407
+
408
+ rf_model = RandomForestRegressor()
409
+ rf_model.fit(X_train, y_train)
410
+
411
+ xgb_model = XGBRegressor()
412
+ xgb_model.fit(X_train, y_train)
413
+
414
+ # Make predictions on the testing data using the trained models
415
+ lr_pred = lr_model.predict(X_test)
416
+ rf_pred = rf_model.predict(X_test)
417
+ xgb_pred = xgb_model.predict(X_test)
418
+
419
+ # Calculate the evaluation metrics for each model
420
+ st.write("**Training regression models to predict value_views using value_shares, value_likes and value_comments**")
421
+ models = ["Linear Regression", "Random Forest", "XGBoost"]
422
+ predictions = [lr_pred, rf_pred, xgb_pred]
423
+
424
+ # Initialize a list to hold the model metrics
425
+ model_metrics = []
426
+
427
+ for model, pred in zip(models, predictions):
428
+ mse = mean_squared_error(y_test, pred)
429
+ mae = mean_absolute_error(y_test, pred)
430
+ r2 = r2_score(y_test, pred)
431
+
432
+ # Append a dictionary of the metrics to the list
433
+ model_metrics.append({"Model": model, "Mean Squared Error": mse, "Mean Absolute Error": mae, "R^2 Score": r2})
434
+
435
+ # Convert the list of dictionaries into a DataFrame
436
+ metrics_df = pd.DataFrame(model_metrics)
437
+
438
+ # Display the DataFrame in Streamlit
439
+ st.write(metrics_df)
440
+
441
+
442
+ x_var = st.sidebar.selectbox("Select X variable", merged_df.columns)
443
+ y_var = st.sidebar.selectbox("Select Y variable", merged_df.columns)
444
+ show_regression_line = False
445
+
446
+ z_var_options = ["None"] + list(merged_df.columns)
447
+ z_var = st.sidebar.selectbox("Select Z variable for 3D charts (if applicable)", z_var_options)
448
+
449
+ # Allow user to select time frequency for resampling
450
+ #time_frequency = st.sidebar.selectbox("Select time frequency", ["Day", "Week", "Month"])
451
+
452
+ #if time_frequency == "Week":
453
+ #data_resampled = data.resample('W').sum()
454
+ #elif time_frequency == "Month":
455
+ #data_resampled = data.resample('M').sum()
456
+ #else:
457
+ #data_resampled = data
458
+ st.subheader("Various plots to represent performance scores for views, shares, likes and comments")
459
+ tab1, tab2, tab3, tab4, tab5, tab6, tab7 = st.tabs(["Line", "Bar", "Scatterplot", "Heatmap",
460
+ "3D Scatterplot", "3D Lineplot", "3D Surfaceplot"])
461
+ with tab1:
462
+ st.write("Lineplot")
463
+ plot_chart(merged_df, "line", x_var, y_var)
464
+
465
+ with tab2:
466
+ st.write("Barplot")
467
+ plot_chart(merged_df, "bar", x_var, y_var)
468
+
469
+ with tab3:
470
+ st.write("Scatterplot")
471
+ show_regression_line = st.checkbox("Show regression line")
472
+ plot_chart(merged_df, "scatter", x_var, y_var, show_regression_line=show_regression_line)
473
+
474
+ with tab4:
475
+ st.write("Heatmap")
476
+ plot_chart(merged_df, "heatmap", x_var, y_var)
477
+
478
+ with tab5:
479
+ st.write("3D Scatterplot")
480
+ if z_var != "None":
481
+ plot_chart(merged_df, "scatter_3d", x_var, y_var, z_var)
482
+
483
+ with tab6:
484
+ st.write("3D Lineplot")
485
+ if z_var != "None":
486
+ plot_chart(merged_df, "line_3d", x_var, y_var, z_var)
487
+
488
+ with tab7:
489
+ st.write("3D Surfaceplot")
490
+ if z_var != "None":
491
+ plot_chart(merged_df, "surface_3d", x_var, y_var, z_var)
492
+
493
+ #with tab8:
494
+ #st.write("Radar chart for 'Last 60 days'")
495
+ #radar_columns = ['value_views', 'value_shares', 'value_likes', 'value_comments']
496
+ #plot_radar_chart(data, radar_columns)
497
+
498
+ tab1, tab2, tab3, tab4 = st.tabs(["vs Views", "vs Shares", "vs Likes", "vs Comments"])
499
+ with tab1:
500
+ st.subheader("Hashtag Performance - Views:")
501
+ #for tag, perf in hashtag_performance.items():
502
+ #st.write(f"{tag}: {perf}")
503
+ #AgGrid(hashtag_performance_views)
504
+ #df1 = pd.DataFrame(list(hashtag_performance_views.items()), columns=["hashtag", "value"])
505
+ # Sort the DataFrame by the 'value' column in descending order
506
+ sorted_df1 = df1.sort_values(by="value_views", ascending=False)
507
+ st.write(sorted_df1)
508
+ # Highlight specific bars (use 'rgba' values for transparency)
509
+ highlighted_bars = ['#fyp', '#tiktok', '#foryou', '#trending', '#viral']
510
+ sorted_df1['color'] = sorted_df1['hashtag'].apply(lambda x: 'black' if x in highlighted_bars else 'red')
511
+ fig = px.bar(sorted_df1, x='hashtag', y='value_views', title='Hashtag performance for the week',
512
+ color='color', color_discrete_map='identity', hover_data={'value_views': ':.2f'})
513
+
514
+ fig.update_layout(title='Hashtag performance for the week - Views', xaxis_title='Hashtag', yaxis_title='Value')
515
+ st.plotly_chart(fig)
516
+
517
+ with tab2:
518
+ st.subheader("Hashtag Performance - Shares:")
519
+ #for tag, perf in hashtag_performance.items():
520
+ #st.write(f"{tag}: {perf}")
521
+ #AgGrid(hashtag_performance_views)
522
+ #df2 = pd.DataFrame(list(hashtag_performance_shares.items()), columns=["hashtag", "value"])
523
+ # Sort the DataFrame by the 'value' column in descending order
524
+ sorted_df2 = df2.sort_values(by="value_shares", ascending=False)
525
+ st.write(sorted_df2)
526
+ # Highlight specific bars (use 'rgba' values for transparency)
527
+ highlighted_bars = ['#fyp', '#tiktok', '#foryou', '#trending', '#viral']
528
+ sorted_df2['color'] = sorted_df2['hashtag'].apply(lambda x: 'black' if x in highlighted_bars else 'blue')
529
+ fig = px.bar(sorted_df2, x='hashtag', y='value_shares', title='Hashtag performance for the week',
530
+ color='color', color_discrete_map='identity', hover_data={'value_shares': ':.2f'})
531
+
532
+ fig.update_layout(title='Hashtag performance for the week - Shares', xaxis_title='Hashtag', yaxis_title='Value')
533
+ st.plotly_chart(fig)
534
+ with tab3:
535
+ st.subheader("Hashtag Performance - Likes:")
536
+ #for tag, perf in hashtag_performance.items():
537
+ #st.write(f"{tag}: {perf}")
538
+ #AgGrid(hashtag_performance_views)
539
+ #df3 = pd.DataFrame(list(hashtag_performance_likes.items()), columns=["hashtag", "value"])
540
+ # Sort the DataFrame by the 'value' column in descending order
541
+ sorted_df3 = df3.sort_values(by="value_likes", ascending=False)
542
+ st.write(sorted_df3)
543
+ # Highlight specific bars (use 'rgba' values for transparency)
544
+ highlighted_bars = ['#fyp', '#tiktok', '#foryou', '#trending', '#viral']
545
+ sorted_df3['color'] = sorted_df3['hashtag'].apply(lambda x: 'black' if x in highlighted_bars else 'green')
546
+ fig = px.bar(sorted_df3, x='hashtag', y='value_likes', title='Hashtag performance for the week',
547
+ color='color', color_discrete_map='identity', hover_data={'value_likes': ':.2f'})
548
+
549
+ fig.update_layout(title='Hashtag performance for the week - Likes', xaxis_title='Hashtag', yaxis_title='Value')
550
+ st.plotly_chart(fig)
551
+ with tab4:
552
+ st.subheader("Hashtag Performance - Comments:")
553
+ #for tag, perf in hashtag_performance.items():
554
+ #st.write(f"{tag}: {perf}")
555
+ #AgGrid(hashtag_performance_views)
556
+ #df4 = pd.DataFrame(list(hashtag_performance_views.items()), columns=["hashtag", "value"])
557
+ # Sort the DataFrame by the 'value' column in descending order
558
+ sorted_df4 = df4.sort_values(by="value_comments", ascending=False)
559
+ st.write(sorted_df4)
560
+ # Highlight specific bars (use 'rgba' values for transparency)
561
+ highlighted_bars = ['#fyp', '#tiktok', '#foryou', '#trending', '#viral']
562
+ sorted_df4['color'] = sorted_df4['hashtag'].apply(lambda x: 'black' if x in highlighted_bars else 'orange')
563
+ fig = px.bar(sorted_df4, x='hashtag', y='value_comments', title='Hashtag performance for the week',
564
+ color='color', color_discrete_map='identity', hover_data={'value_comments': ':.2f'})
565
+
566
+ fig.update_layout(title='Hashtag performance for the week - Comments', xaxis_title='Hashtag', yaxis_title='Value')
567
+ st.plotly_chart(fig)
568
+
569
+
570
+ # Calculate the similarity between hashtags
571
+ #similarity_matrix = cosine_similarity(list(hashtag_vectors.values()))
572
+ #st.write(similarity_matrix)
573
+ # Convert the similarity matrix into a DataFrame
574
+ #similarity_df = pd.DataFrame(similarity_matrix, index=unique_hashtags, columns=unique_hashtags)
575
+ #st.write(similarity_df)
576
+ # Calculate the correlation between hashtag similarity and performance
577
+ #correlations = np.corrcoef(similarity_df, data["Total views"], rowvar=False)
578
+ #st.write(correlations)
579
+
580
+ #with tab2:
581
+ #if 'video_view_within_days' not in data.columns: #Video Posts
582
+ #pass
583
+
pages/followers.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import datetime
5
+ import plotly.express as px
6
+ import plotly.graph_objects as go
7
+ import statsmodels.api as sm
8
+ from millify import millify
9
+ from sklearn.linear_model import LinearRegression
10
+ from sklearn.metrics import r2_score
11
+ from st_aggrid import AgGrid
12
+ import io
13
+ import openpyxl
14
+ #from st_pages import Page, show_pages, add_page_title
15
+
16
+ # Set page title
17
+ st.set_page_config(page_title="Followers - Tiktok Analytics Dashboard", page_icon = "📊", layout = "centered", initial_sidebar_state = "auto")
18
+
19
+ st.header("Followers")
20
+ st.markdown("""Upload your files here to load your data!
21
+
22
+ *'Follower activity', 'Top territories', 'Gender', 'Total followers' (xlsx or csv format)*
23
+ """)
24
+
25
+ uploaded_files = st.file_uploader(
26
+ "Choose CSV or Excel files to upload",
27
+ accept_multiple_files=True,
28
+ type=['csv', 'xlsx'])
29
+
30
+ if uploaded_files:
31
+ data_list = []
32
+ # read the file
33
+ with st.expander("View uploaded data"):
34
+ for uploaded_file in uploaded_files:
35
+ st.write("▾ Filename:", uploaded_file.name)
36
+ bytes_data = uploaded_file.read()
37
+ data = None
38
+ if uploaded_file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
39
+ data = pd.read_excel(io.BytesIO(bytes_data))
40
+ AgGrid(data)
41
+ else:
42
+ data = pd.read_csv(io.StringIO(bytes_data.decode('utf-8')))
43
+ AgGrid(data)
44
+
45
+ data_list.append(data)
46
+
47
+ tab1, tab2, tab3, tab4, tab5 = st.tabs(["Follower Activity", "Gender", "Top Territories", "Followers", "Difference in Daily Followers"])
48
+ for data in data_list:
49
+ #st.write(data.columns)
50
+ #st.write(data)
51
+ with tab1:
52
+ if 'Active followers' in data.columns:
53
+ # create a list of all unique dates in the data
54
+ unique_dates = data['Date'].unique()
55
+
56
+ # Add a date filter widget
57
+ filter_type = st.sidebar.radio("Select filter type for Follower Activity", ["Individual date", "Total date range"])
58
+ if filter_type == "Individual date":
59
+ selected_date = st.sidebar.selectbox("Select a date", unique_dates)
60
+
61
+ # Filter the data to only include the selected date
62
+ filtered_data = data[data['Date'] == selected_date]
63
+
64
+ # Calculate the average number of followers for the selected date
65
+ avg_followers = filtered_data['Active followers'].mean()
66
+
67
+
68
+ elif filter_type == "Total date range":
69
+ # Filter the data to include the entire date range
70
+ filtered_data = data
71
+ # Calculate the average number of followers for the entire date range
72
+ avg_followers = filtered_data['Active followers'].mean()
73
+
74
+ #else:
75
+ # Get the start and end dates using st.date_input
76
+ #start_date = st.sidebar.date_input("Select start date", data['Date'].min(), data['Date'].max())
77
+ #end_date = st.sidebar.date_input("Select end date", data['Date'].min(), data['Date'].max())
78
+
79
+ # Filter the data based on the start and end dates
80
+ #filtered_data = data[(data['Date'] >= start_date) & (data['Date'] <= end_date)]
81
+
82
+ # create a datetime column from the date and hour columns
83
+ filtered_data['Datetime'] = pd.to_datetime(filtered_data['Date'] + ' ' + (filtered_data['Hour'] - 1).astype(str) + ':00:00')
84
+
85
+ # group the data by the datetime column and calculate the sum of active followers
86
+ grouped_data = filtered_data.groupby("Datetime")["Active followers"].sum().reset_index()
87
+
88
+ # create a line chart using Plotly Express
89
+ fig = px.line(filtered_data, x="Datetime", y="Active followers", title="Follower Activity")
90
+
91
+ # Add average line
92
+ 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'))
93
+
94
+ # Annotate average value onto average line
95
+ fig.add_annotation(x=filtered_data['Datetime'].max(), y=avg_followers, text=f"Average: {avg_followers:.0f}", showarrow=True, arrowhead=2)
96
+
97
+ st.plotly_chart(fig)
98
+ with tab2:
99
+ if 'Gender' in data.columns:
100
+ #st.write("Pie chart for 'Gender'")
101
+ gender_data = data.groupby('Gender')['Distribution'].apply(lambda x: pd.to_numeric(x.str.replace('%', ''), errors='coerce').dropna().mean()).reset_index()
102
+ fig = px.pie(gender_data, values='Distribution', names='Gender', title='Gender Distribution (%)',
103
+ color_discrete_sequence=['#1f77b4', '#ff7f0e'])
104
+ st.plotly_chart(fig)
105
+ with tab3:
106
+ if 'Top territories' in data.columns:
107
+ territories_data = data.groupby('Top territories')['Distribution'].apply(lambda x: pd.to_numeric(x.str.replace('%', ''), errors='coerce').dropna().mean()).reset_index()
108
+ territories_data = territories_data.sort_values(by='Distribution', ascending=True)
109
+ #st.write("Top 5 territories by distribution")
110
+ fig = px.bar(territories_data, x='Distribution', y='Top territories', title='Distribution (%) of Top 5 Countries',
111
+ color_discrete_sequence=px.colors.qualitative.Dark2)
112
+ st.plotly_chart(fig)
113
+ with tab4:
114
+ if 'Followers' in data.columns:
115
+ fig = px.line(data, x="Date", y="Followers", title="Total Followers", markers=True,
116
+ hover_data={'Followers': ':.2f'})
117
+ st.plotly_chart(fig)
118
+ with tab5:
119
+ if 'Difference in followers from previous day' in data.columns:
120
+ # Create a custom color scale
121
+ def custom_color_scale(val):
122
+ if val >= 0:
123
+ return 'rgba(54, 164, 235, 0.8)'
124
+ else:
125
+ return 'rgba(255, 77, 77, 0.8)'
126
+ fig = px.bar(data, x="Date", y="Difference in followers from previous day", title="Difference in Daily Followers",
127
+ text='Difference in followers from previous day', color='Difference in followers from previous day',
128
+ 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']})
129
+ # Customize the layout
130
+ fig.update_layout(
131
+ title="Difference in Daily Followers",
132
+ xaxis_title="Date",
133
+ yaxis_title="Difference in Daily Followers",
134
+ showlegend=False,
135
+ plot_bgcolor="white",
136
+ yaxis=dict(zeroline=True, zerolinewidth=2, zerolinecolor="black"), # Add a line at y=0
137
+ )
138
+ st.plotly_chart(fig)
139
+
140
+
141
+
pages/overview.py ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import plotly.express as px
5
+ import plotly.graph_objects as go
6
+ import statsmodels.api as sm
7
+ from millify import millify
8
+ from sklearn.linear_model import LinearRegression
9
+ from sklearn.metrics import r2_score
10
+ from st_aggrid import AgGrid
11
+ import io
12
+ import openpyxl
13
+ #from st_pages import Page, show_pages, add_page_title
14
+ from streamlit_extras.metric_cards import style_metric_cards
15
+
16
+ # Set page title
17
+ st.set_page_config(page_title="Overview - Tiktok Analytics Dashboard", page_icon = "📊", layout = "centered", initial_sidebar_state = "auto")
18
+
19
+
20
+ st.header("Overview")
21
+ st.markdown("""Upload your files here to load your data!
22
+
23
+ *'Last 60 days' (xlsx or csv format)*
24
+ """)
25
+
26
+ def plot_chart(data, chart_type, x_var, y_var, z_var=None, show_regression_line=False, show_r_squared=False):
27
+ scatter_marker_color = 'green'
28
+ regression_line_color = 'red'
29
+ if chart_type == "line":
30
+ fig = px.line(data, x=x_var, y=y_var)
31
+
32
+ elif chart_type == "bar":
33
+ fig = px.bar(data, x=x_var, y=y_var)
34
+
35
+ elif chart_type == "scatter":
36
+ fig = px.scatter(data, x=x_var, y=y_var, color_discrete_sequence=[scatter_marker_color])
37
+
38
+ if show_regression_line and x_var != 'Date':
39
+ X = data[x_var].values.reshape(-1, 1)
40
+ y = data[y_var].values.reshape(-1, 1)
41
+ model = LinearRegression().fit(X, y)
42
+ y_pred = model.predict(X)
43
+ r_squared = r2_score(y, y_pred) # Calculate R-squared value
44
+
45
+ fig.add_trace(
46
+ go.Scatter(x=data[x_var], y=y_pred[:, 0], mode='lines', name='Regression Line', line=dict(color=regression_line_color))
47
+ )
48
+
49
+ # Add R-squared value as a text annotation
50
+ fig.add_annotation(
51
+ x=data[x_var].max(),
52
+ y=y_pred[-1, 0],
53
+ text=f"R-squared: {r_squared:.4f}",
54
+ showarrow=False,
55
+ font=dict(size=14),
56
+ bgcolor='rgba(255, 255, 255, 0.8)',
57
+ bordercolor='black',
58
+ borderwidth=1,
59
+ borderpad=4
60
+ )
61
+
62
+ elif chart_type == "heatmap":
63
+ fig = px.imshow(data, color_continuous_scale='Inferno')
64
+
65
+ elif chart_type == "scatter_3d":
66
+ if z_var is not None:
67
+ fig = px.scatter_3d(data, x=x_var, y=y_var, z=z_var, color=data.columns[0])
68
+ else:
69
+ st.warning("Please select Z variable for 3D line plot.")
70
+ return
71
+
72
+ elif chart_type == "line_3d":
73
+ if z_var is not None:
74
+ fig = go.Figure(data=[go.Scatter3d(x=data[x_var], y=data[y_var], z=data[z_var], mode='lines')])
75
+ fig.update_layout(scene=dict(xaxis_title=x_var, yaxis_title=y_var, zaxis_title=z_var)) # Set the axis name
76
+ else:
77
+ st.warning("Please select Z variable for 3D line plot.")
78
+ return
79
+
80
+ elif chart_type == "surface_3d":
81
+ if z_var is not None:
82
+ fig = go.Figure(data=[go.Surface(z=data.values)])
83
+ fig.update_layout(scene=dict(xaxis_title=x_var, yaxis_title=y_var, zaxis_title=z_var)) # Set the axis name
84
+ else:
85
+ st.warning("Please select Z variable for 3D line plot.")
86
+ return
87
+
88
+ elif chart_type == "radar":
89
+ fig = go.Figure()
90
+ for col in data.columns[1:]:
91
+ fig.add_trace(go.Scatterpolar(r=data[col], theta=data[x_var], mode='lines', name=col))
92
+ fig.update_layout(polar=dict(radialaxis=dict(visible=True, range=[data[data.columns[1:]].min().min(), data[data.columns[1:]].max().max()])))
93
+
94
+ st.plotly_chart(fig)
95
+
96
+ def plot_radar_chart(data, columns):
97
+ df = data[columns]
98
+ fig = go.Figure()
99
+
100
+ for i in range(len(df)):
101
+ date_label = data.loc[i, 'Date']
102
+ fig.add_trace(go.Scatterpolar(
103
+ r=df.loc[i].values,
104
+ theta=df.columns,
105
+ fill='toself',
106
+ name=date_label
107
+ ))
108
+
109
+ fig.update_layout(
110
+ polar=dict(
111
+ radialaxis=dict(
112
+ visible=True,
113
+ range=[0, df.max().max()]
114
+ )
115
+ ),
116
+ showlegend=True
117
+ )
118
+
119
+ st.plotly_chart(fig)
120
+
121
+
122
+ uploaded_files = st.file_uploader(
123
+ "Choose CSV or Excel files to upload",
124
+ accept_multiple_files=True,
125
+ type=['csv', 'xlsx'])
126
+
127
+ if uploaded_files:
128
+ data_list = []
129
+ for uploaded_file in uploaded_files:
130
+ # read the file
131
+ with st.expander("View uploaded data"):
132
+ st.write("▾ Filename:", uploaded_file.name)
133
+ bytes_data = uploaded_file.read()
134
+ data = None
135
+ if uploaded_file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
136
+ data = pd.read_excel(io.BytesIO(bytes_data))
137
+ AgGrid(data)
138
+ else:
139
+ data = pd.read_csv(io.StringIO(bytes_data.decode('utf-8')))
140
+ AgGrid(data)
141
+
142
+ # preview the data
143
+ #st.write('Preview of', uploaded_file.name)
144
+ # st.write(data)
145
+
146
+ # convert "Date" column to datetime object and set as index
147
+ #data['Date'] = pd.to_datetime(data['Date'])
148
+ #data.set_index('Date', inplace=True)
149
+
150
+ data_list.append(data)
151
+
152
+
153
+ # Replace "data" with your actual dataframe
154
+ sums = data.sum()
155
+ #st.write(sums) # To check table values for indexing
156
+ col1, col2, col3, col4, col5 = st.columns((5))
157
+ with col1:
158
+ st.metric(label="Video views", value=sums[1])
159
+ with col2:
160
+ st.metric(label="Profile views", value=sums[2])
161
+ with col3:
162
+ st.metric(label="Likes", value=sums[3])
163
+ with col4:
164
+ st.metric(label="Comments", value=sums[4])
165
+ with col5:
166
+ st.metric(label="Shares", value=sums[5])
167
+ #style_metric_cards()
168
+
169
+ # Generate specific charts based on the file name
170
+ if uploaded_file.name == "Last 60 days.xlsx" or uploaded_file.name == "Last 60 days.csv":
171
+
172
+ x_var = st.sidebar.selectbox("Select X variable for Last 60 days", data.columns)
173
+ y_var = st.sidebar.selectbox("Select Y variable for Last 60 days", data.columns)
174
+ show_regression_line = False
175
+
176
+ z_var_options = ["None"] + list(data.columns)
177
+ z_var = st.sidebar.selectbox("Select Z variable for 3D charts (if applicable)", z_var_options)
178
+
179
+ # Allow user to select time frequency for resampling
180
+ #time_frequency = st.sidebar.selectbox("Select time frequency", ["Day", "Week", "Month"])
181
+
182
+ #if time_frequency == "Week":
183
+ #data_resampled = data.resample('W').sum()
184
+ #elif time_frequency == "Month":
185
+ #data_resampled = data.resample('M').sum()
186
+ #else:
187
+ #data_resampled = data
188
+
189
+ tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8 = st.tabs(["Line", "Bar", "Scatterplot", "Heatmap",
190
+ "3D Scatterplot", "3D Lineplot", "3D Surfaceplot", "Radar chart"])
191
+ with tab1:
192
+ st.write("Lineplot for 'Last 60 days'")
193
+ plot_chart(data, "line", x_var, y_var)
194
+
195
+ with tab2:
196
+ st.write("Barplot for 'Last 60 days'")
197
+ plot_chart(data, "bar", x_var, y_var)
198
+
199
+ with tab3:
200
+ st.write("Scatterplot for 'Last 60 days'")
201
+ show_regression_line = st.checkbox("Show regression line for Last 60 days scatterplot (does not apply when X = Date)")
202
+ plot_chart(data, "scatter", x_var, y_var, show_regression_line=show_regression_line)
203
+
204
+ with tab4:
205
+ st.write("Heatmap for 'Last 60 days'")
206
+ plot_chart(data, "heatmap", x_var, y_var)
207
+
208
+ with tab5:
209
+ st.write("3D Scatterplot for 'Last 60 days'")
210
+ if z_var != "None":
211
+ plot_chart(data, "scatter_3d", x_var, y_var, z_var)
212
+
213
+ with tab6:
214
+ st.write("3D Lineplot for 'Last 60 days'")
215
+ if z_var != "None":
216
+ plot_chart(data, "line_3d", x_var, y_var, z_var)
217
+
218
+ with tab7:
219
+ st.write("3D Surfaceplot for 'Last 60 days'")
220
+ if z_var != "None":
221
+ plot_chart(data, "surface_3d", x_var, y_var, z_var)
222
+
223
+ with tab8:
224
+ st.write("Radar chart for 'Last 60 days'")
225
+ radar_columns = ['Video views', 'Profile views', 'Likes', 'Comments', 'Shares']
226
+ plot_radar_chart(data, radar_columns)
227
+ # Add more conditions for other specific file names if needed
requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit==1.22.0
2
+ pandas==1.3.5
3
+ numpy==1.21.6
4
+ plotly==5.14.1
5
+ statsmodels==0.13.5
6
+ millify==0.1.1
7
+ scikit-learn==1.0.2
8
+ streamlit-aggrid==0.3.2
9
+ emoji==2.2.0
10
+ openpyxl
11
+ gensim==3.3.0
12
+ xgboost==1.6.2
13
+ matplotlib==3.4.3
14
+ seaborn==0.12.2
15
+