File size: 8,892 Bytes
181806d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1518b5c
181806d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
import re

# Configuration de la page
st.set_page_config(
    page_title="Analyse des tendances YouTube 2025",
    page_icon="📊",
    layout="wide"
)

# Fonction pour charger les données
@st.cache_data
def load_data():
    # Chargement des données
    df = pd.read_csv('tendances_2025_final.csv')
    categories = pd.read_csv('category.csv', sep=';')
    
    # Conversion des types de données
    numeric_cols = ['view_count', 'likes', 'dislikes', 'comment_count']
    for col in numeric_cols:
        df[col] = pd.to_numeric(df[col], errors='coerce')
    
    # Extraction de la date de trending correctement formatée
    # Le format semble être YY.DD.MM
    df['trending_date_formatted'] = pd.to_datetime(df['trending_date'].apply(
        lambda x: '20' + x.split('.')[0] + '-' + x.split('.')[2] + '-' + x.split('.')[1]
    ), errors='coerce')
    
    # Conversion de la date de publication
    df['publishedAt'] = pd.to_datetime(df['publishedAt'], errors='coerce')
    
    # Conversion de la durée en minutes
    def convert_duration(duration_str):
        if pd.isna(duration_str):
            return np.nan
        parts = duration_str.split(':')
        if len(parts) == 2:  # MM:SS
            return int(parts[0]) + int(parts[1])/60
        elif len(parts) == 3:  # HH:MM:SS
            return int(parts[0])*60 + int(parts[1]) + int(parts[2])/60
        return np.nan
    
    df['duration_minutes'] = df['duration'].apply(convert_duration)
    
    # Ajout des noms de catégories
    df = df.merge(categories, left_on='categoryId', right_on='ID', how='left')
    
    # Calcul des métriques supplémentaires
    df['likes_per_view'] = df['likes'] / df['view_count']
    df['comments_per_view'] = df['comment_count'] / df['view_count']
    
    return df

# Fonction pour créer un histogramme
def create_histogram(df, column, title, color='#1f77b4', nbins=20):
    fig = px.histogram(df, x=column, nbins=nbins, title=title)
    fig.update_layout(bargap=0.1)
    return fig

# Fonction pour créer un graphique en barres
def create_bar_chart(df, x_col, y_col, title, color='#1f77b4'):
    fig = px.bar(df, x=x_col, y=y_col, title=title, color_discrete_sequence=[color])
    return fig

# Fonction pour créer un nuage de points
def create_scatter_plot(df, x_col, y_col, size_col, hover_data, title):
    fig = px.scatter(df, x=x_col, y=y_col, size=size_col, 
                     hover_data=hover_data, title=title)
    return fig

# Fonction pour créer une carte de chaleur
def create_heatmap(df, categories, metrics):
    # Création d'un DataFrame pivot avec les moyennes par catégorie
    heatmap_data = pd.DataFrame()
    
    for metric in metrics:
        for cat in categories:
            cat_data = df[df['Category name'] == cat]
            if not cat_data.empty:
                heatmap_data.loc[cat, metric] = cat_data[metric].mean()
    
    # Normalisation des données pour la carte de chaleur
    normalized_data = (heatmap_data - heatmap_data.min()) / (heatmap_data.max() - heatmap_data.min())
    
    # Création de la carte de chaleur
    fig = go.Figure(data=go.Heatmap(
        z=normalized_data.values,
        x=normalized_data.columns,
        y=normalized_data.index,
        colorscale='Viridis',
        hovertemplate='Catégorie: %{y}<br>Métrique: %{x}<br>Valeur: %{z}<extra></extra>'
    ))
    
    fig.update_layout(
        title='Carte de chaleur des métriques par catégorie',
        xaxis_title='Métriques',
        yaxis_title='Catégories'
    )
    
    return fig

# Chargement des données
df = load_data()

# Sidebar pour les filtres
st.sidebar.title("Filtres")

# Filtre par catégorie
categories = sorted(df['Category name'].dropna().unique())
selected_categories = st.sidebar.multiselect(
    "Sélectionner les catégories",
    categories,
    default=categories[:3]  # Par défaut, sélectionne les 3 premières catégories
)

# Filtre par date de tendance
min_date = df['trending_date_formatted'].min().date()
max_date = df['trending_date_formatted'].max().date()
date_range = st.sidebar.date_input(
    "Période de tendance",
    [min_date, max_date],
    min_value=min_date,
    max_value=max_date
)

# Filtre par chaîne YouTube
channels = sorted(df['channelTitle'].dropna().unique())
selected_channels = st.sidebar.multiselect(
    "Sélectionner les chaînes",
    channels,
    default=[]
)

# Application des filtres
filtered_df = df.copy()

if selected_categories:
    filtered_df = filtered_df[filtered_df['Category name'].isin(selected_categories)]

if len(date_range) == 2:
    start_date, end_date = date_range
    filtered_df = filtered_df[
        (filtered_df['trending_date_formatted'].dt.date >= start_date) &
        (filtered_df['trending_date_formatted'].dt.date <= end_date)
    ]

if selected_channels:
    filtered_df = filtered_df[filtered_df['channelTitle'].isin(selected_channels)]

# Titre principal
st.title("📊 Analyse des tendances YouTube 2025")

# Métriques principales
st.header("📈 Indicateurs clés")
col1, col2, col3, col4 = st.columns(4)

with col1:
    st.metric("Nombre de vidéos", f"{len(filtered_df):,}")
    
with col2:
    avg_views = filtered_df['view_count'].mean()
    st.metric("Vues moyennes", f"{avg_views:,.0f}")
    
with col3:
    avg_likes_per_view = filtered_df['likes_per_view'].mean() * 100
    st.metric("Likes/Vues moyen", f"{avg_likes_per_view:.2f}%")
    
with col4:
    avg_duration = filtered_df['duration_minutes'].mean()
    st.metric("Durée moyenne", f"{avg_duration:.1f} min")

# Visualisations
st.header("🔍 Visualisations")

# Distribution des vues
col1, col2 = st.columns(2)

with col1:
    views_hist = create_histogram(filtered_df, 'view_count', 'Distribution des vues', color='#FF0000', nbins=30)
    st.plotly_chart(views_hist, use_container_width=True)

with col2:
    duration_hist = create_histogram(filtered_df, 'duration_minutes', 'Distribution des durées (minutes)', color='#00BFD6', nbins=25)
    st.plotly_chart(duration_hist, use_container_width=True)

# Engagement par catégorie
col1, col2 = st.columns(2)

with col1:
    category_engagement = filtered_df.groupby('Category name').agg({
        'likes_per_view': 'mean',
        'comments_per_view': 'mean'
    }).reset_index()
    
    category_engagement['likes_per_view'] = category_engagement['likes_per_view'] * 100
    category_engagement['comments_per_view'] = category_engagement['comments_per_view'] * 100
    
    likes_by_category = create_bar_chart(
        category_engagement, 
        'Category name', 
        'likes_per_view', 
        'Taux de likes par catégorie (%)',
        color='#FF9900'
    )
    st.plotly_chart(likes_by_category, use_container_width=True)

with col2:
    comments_by_category = create_bar_chart(
        category_engagement, 
        'Category name', 
        'comments_per_view', 
        'Taux de commentaires par catégorie (%)',
        color='#00CC96'
    )
    st.plotly_chart(comments_by_category, use_container_width=True)

# Nuage de points des vidéos
scatter_plot = create_scatter_plot(
    filtered_df,
    'view_count',
    'likes_per_view',
    'duration_minutes',
    ['title', 'channelTitle', 'Category name'],
    'Relation entre vues et taux de likes'
)
st.plotly_chart(scatter_plot, use_container_width=True)

# Carte de chaleur des métriques par catégorie
if selected_categories:
    metrics = ['view_count', 'likes_per_view', 'comments_per_view', 'duration_minutes']
    heatmap = create_heatmap(filtered_df, selected_categories, metrics)
    st.plotly_chart(heatmap, use_container_width=True)

# Top vidéos par vues
st.header("🏆 Top 10 des vidéos les plus vues")
top_videos = filtered_df.nlargest(10, 'view_count')[['title', 'channelTitle', 'Category name', 'view_count', 'likes', 'comment_count', 'duration_minutes']]
top_videos = top_videos.rename(columns={
    'title': 'Titre',
    'channelTitle': 'Chaîne',
    'Category name': 'Catégorie',
    'view_count': 'Vues',
    'likes': 'Likes',
    'comment_count': 'Commentaires',
    'duration_minutes': 'Durée (min)'
})
st.dataframe(top_videos, use_container_width=True)

# Téléchargement des données filtrées
st.header("📥 Télécharger les données filtrées")
csv = filtered_df.to_csv(index=False).encode('utf-8')
st.download_button(
    label="Télécharger en CSV",
    data=csv,
    file_name="youtube_trends_filtered.csv",
    mime="text/csv",
)

# Informations sur l'application
st.sidebar.markdown("---")
st.sidebar.info("""
**À propos de cette application**

Cette application analyse les tendances YouTube de 2025.
Vous pouvez filtrer les données par catégorie, date et chaîne pour explorer les métriques importantes.

Données mises à jour le 9 avril 2025.
""")