Lesson 10 · Social Media Content Analytics
Loading Social Media Data from CSV and APIs
In this lesson, we will learn how to load real social media data using Python. We will explore both CSV datasets and loading data from APIs like YouTube.…
- CourseSocial Media Content Analytics
- Lesson10 of 41
- Video31 min
- FormatJupyter notebook · 23 code cells
- Data1 dataset
What you'll learn
Datasets used in this lesson
Save these next to the notebook. In Google Colab, upload them with the 📁 icon on the left first.
- social_media_posts.csv28.4 KB
📓 Full notebook
Download .ipynbLoading Social Media Data from CSV and APIs#
- In this lesson, we will learn how to load real social media data using Python.
- We will explore both CSV datasets and loading data from APIs like YouTube.
- This is important because understanding content engagement starts with getting the right data.
- For content creators and businesses, the ability to analyze your own or public data leads to better strategies.
- By the end of this lesson, you will be able to load social media datasets, explore key engagement metrics, and spot top-performing content.
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import os, pickle
from pathlib import Path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
Understanding Core Social Media Analytics Concepts#
- Social media datasets usually represent videos, posts, channels, or user interactions.
- Engagement metrics like views, likes, comments, shares, and CTR show how audiences respond to content.
- Metrics such as watch time or engagement rate can indicate content quality or popularity.
- It is important not to confuse absolute counts with rates: ten thousand likes is huge for a small creator but low for a superstar.
- A common mistake is aggregating metrics incorrectly, such as mixing different time periods or ignoring platform differences.
- Always check if data is missing, mislabeled, or grouped the wrong way before running deeper analyses.
# Beginner Example 1: Load social media content data from a DataFrame
np.random.seed(42)
n_posts = 500
views = np.random.randint(100, 100000, n_posts)
df = pd.DataFrame({
'post_id': range(1, n_posts+1),
'platform': np.random.choice(['YouTube','Instagram','TikTok'], n_posts),
'date': pd.date_range('2023-01-01', periods=n_posts, freq='6h'),
'views': views,
'likes': (views * np.random.uniform(0.02, 0.15, n_posts)).astype(int),
'comments': (views * np.random.uniform(0.001, 0.05, n_posts)).astype(int),
'shares': (views * np.random.uniform(0.001, 0.03, n_posts)).astype(int)
})
print(df.shape)
print(df.head(3))
# Beginner Example 2: Calculate engagement rate for each post
df['engagement_rate'] = ((df['likes'] + df['comments'] + df['shares']) / df['views'] * 100).round(2)
print(df[['platform', 'views', 'likes', 'comments', 'shares', 'engagement_rate']].head(3))
# Beginner Example 3: Save the dataset to CSV and reload it
csv_path = 'social_media_posts.csv'
df.to_csv(csv_path, index=False)
df_loaded = pd.read_csv(csv_path)
print(df_loaded.head(3))
# Intermediate Example 1: Load YouTube trending data from the API, or use synthetic fallback
SCOPES = ['https://www.googleapis.com/auth/youtube.readonly']
def get_yt_service():
api_key = os.environ.get('YOUTUBE_API_KEY')
if api_key:
return build('youtube', 'v3', developerKey=api_key)
if Path('client_secret.json').exists():
creds = None
if Path('token_ro.pickle').exists():
with open('token_ro.pickle', 'rb') as f:
creds = pickle.load(f)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token_ro.pickle', 'wb') as f:
pickle.dump(creds, f)
return build('youtube', 'v3', credentials=creds)
raise EnvironmentError('Set YOUTUBE_API_KEY or provide client_secret.json')
def fetch_yt_trending(max_results=200, region='US'):
youtube = get_yt_service()
records, token = [], None
while len(records) < max_results:
resp = youtube.videos().list(
part='snippet,statistics',
chart='mostPopular',
regionCode=region,
maxResults=min(50, max_results - len(records)),
pageToken=token
).execute()
for item in resp.get('items', []):
s = item['snippet']; st = item.get('statistics', {})
records.append({
'video_id': item['id'],
'trending_date': pd.Timestamp.today().date(),
'title': s.get('title', ''),
'channel_title': s.get('channelTitle', ''),
'category_id': s.get('categoryId', ''),
'views': int(st.get('viewCount', 0)),
'likes': int(st.get('likeCount', 0)),
'comment_count': int(st.get('commentCount', 0)),
})
token = resp.get('nextPageToken')
if not token: break
return pd.DataFrame(records)
try:
yt_df = fetch_yt_trending()
print('Live trending data:', yt_df.shape)
except Exception as e:
print(f'Falling back to synthetic: {e}')
n = 1000
np.random.seed(42)
yt_df = pd.DataFrame({
'video_id': [f'vid{i}' for i in range(n)],
'trending_date': pd.date_range('2023-01-01', periods=n, freq='D'),
'title': [f'Video Title {i}' for i in range(n)],
'channel_title': np.random.choice(['ChannelA','ChannelB','ChannelC'], n),
'category_id': np.random.choice([1,2,10,22,24,28], n),
'views': np.random.randint(10000, 5000000, n),
'likes': np.random.randint(100, 200000, n),
'comment_count': np.random.randint(10, 50000, n),
})
print('Synthetic fallback:', yt_df.shape)
print(yt_df.head(3))
# Intermediate Example 2: List the top 5 most-viewed trending videos
top_videos = yt_df.sort_values('views', ascending=False).head(5)
print(top_videos[['title', 'channel_title', 'views', 'likes', 'comment_count']])
# Intermediate Example 3: Compute average view and like counts by channel
channel_summary = yt_df.groupby('channel_title')[['views', 'likes']].mean().sort_values('views', ascending=False).head(5)
print(channel_summary)
# Intermediate Example 4: Import a YouTube analytics-style dataset (simulated)
np.random.seed(42)
n_videos = 300
views = np.random.randint(100, 500000, n_videos)
analytics_df = pd.DataFrame({
'video_id': range(1, n_videos+1),
'publish_date': pd.date_range('2022-01-01', periods=n_videos, freq='D'),
'views': views,
'watch_time': np.random.randint(1000, 500000, n_videos),
'likes': (views * np.random.uniform(0.01, 0.08, n_videos)).astype(int),
'comments': (views * np.random.uniform(0.001, 0.02, n_videos)).astype(int),
'ctr': np.round(np.random.uniform(2, 10, n_videos), 2)
})
print(analytics_df.head(3))
# Intermediate Example 5: Find videos with highest engagement rate
analytics_df['engagement_rate'] = ((analytics_df['likes'] + analytics_df['comments']) / analytics_df['views'] * 100).round(2)
best_engagement = analytics_df.sort_values('engagement_rate', ascending=False).head(5)
print(best_engagement[['video_id', 'views', 'likes', 'comments', 'engagement_rate']])
# Intermediate Example 6: Analyze posting frequency and total views over time
posts_per_month = analytics_df.groupby(analytics_df['publish_date'].dt.to_period('M')).size()
views_per_month = analytics_df.groupby(analytics_df['publish_date'].dt.to_period('M'))['views'].sum()
summary = pd.DataFrame({'posts': posts_per_month, 'total_views': views_per_month})
print(summary)
# Advanced Example 1: Detect top rising channels by trending appearances
trending_counts = yt_df['channel_title'].value_counts().head(5)
print(trending_counts)
# Advanced Example 2: Find categories with the highest average engagement rates
if 'engagement_rate' not in yt_df.columns:
yt_df['engagement_rate'] = ((yt_df['likes'] + yt_df['comment_count']) / yt_df['views'] * 100).round(2)
cat_summary = yt_df.groupby('category_id')['engagement_rate'].mean().sort_values(ascending=False).head(5)
print(cat_summary)
# Advanced Example 3: Import a time series dataset and analyze daily engagement
np.random.seed(42)
n_days = 365
dates = pd.date_range('2023-01-01', periods=n_days, freq='D')
views = np.random.randint(1000, 50000, n_days)
likes = (views * np.random.uniform(0.03, 0.12, n_days)).astype(int)
ts_df = pd.DataFrame({
'date': dates,
'views': views,
'likes': likes,
'engagement_rate': np.round(likes / views * 100, 2)
})
print(ts_df.head(3))
# Advanced Example 4: Visualize daily views and engagement rate as simple trend lines
import matplotlib.pyplot as plt
plt.figure(figsize=(10,4))
plt.plot(ts_df['date'], ts_df['views'], label='Views')
plt.plot(ts_df['date'], ts_df['engagement_rate'], label='Engagement Rate (%)')
plt.xlabel('Date')
plt.legend()
plt.title('Daily Views and Engagement Rate Over Time')
plt.tight_layout()
plt.savefig('daily_trends.png')
plt.close()
# Error Handling 1: Dealing with missing engagement fields
df_missing = df.copy()
df_missing.loc[::50, 'likes'] = np.nan
print(f"Posts with missing likes: {df_missing['likes'].isna().sum()}")
df_missing['likes'] = df_missing['likes'].fillna(0)
print(f"After fill, missing likes: {df_missing['likes'].isna().sum()}")
# Error Handling 2: Preventing division by zero in engagement rate calculation
df_zero = df.copy()
df_zero['views'].iloc[0:3] = 0
df_zero['engagement_rate'] = np.where(df_zero['views'] == 0, 0, ((df_zero['likes'] + df_zero['comments'] + df_zero['shares']) / df_zero['views'] * 100).round(2))
print(df_zero[['views', 'likes', 'engagement_rate']].head(5))
# Error Handling 3: Aggregation mistake - sum vs average
agg_sum = df.groupby('platform')[['likes','comments']].sum()
agg_avg = df.groupby('platform')[['likes','comments']].mean()
print('Sum aggregation:')
print(agg_sum)
print('Average aggregation:')
print(agg_avg.head())
# Error Handling 4: Misinterpreting CTR - raw count vs percent
analytics_df['ctr_fake_raw'] = (analytics_df['ctr'] * analytics_df['views'] / 100).astype(int)
print(analytics_df[['views', 'ctr', 'ctr_fake_raw']].head(3))
# Best Practices 1: Benchmarking content performance against category averages
cat_avg_engagement = yt_df.groupby('category_id')['engagement_rate'].mean()
yt_df['category_benchmarking'] = yt_df['engagement_rate'] / yt_df['category_id'].map(cat_avg_engagement)
print(yt_df[['title','category_id','engagement_rate','category_benchmarking']].head(5))
# Best Practices 2: Segmenting audience performance by platform
platform_stats = df.groupby('platform')[['views', 'likes', 'comments', 'shares', 'engagement_rate']].mean()
print(platform_stats)
# Best Practices 3: Detecting time-based content growth
monthly_growth = analytics_df.set_index('publish_date').resample('M')['views'].sum()
growth_pct = monthly_growth.pct_change().fillna(0).round(2)
for month, growth in zip(monthly_growth.index.strftime('%Y-%m'), growth_pct):
print(f'Month {month}: total views={monthly_growth[month]}, growth={growth*100:.1f}%')
SOCIAL MEDIA ANALYTICS: End-to-End Example#
- Let us combine what we have learned and deliver an actual content strategy recommendation.
- We will use real or simulated YouTube trending data.
- Our task: Find the top 3 channels by total engagement (likes + comments), and recommend when to post for maximum reach.
- By the end, you will have practiced loading, analyzing, and generating actionable insights from large social media datasets.
# End-to-End: Find top 3 channels by total engagement
yt_df['total_engagement'] = yt_df['likes'] + yt_df['comment_count']
top_channels = yt_df.groupby('channel_title')['total_engagement'].sum().sort_values(ascending=False).head(3)
print(top_channels)
# End-to-End: Recommend best posting time by analyzing trending video dates
if 'trending_date' in yt_df.columns:
yt_df['trending_date'] = pd.to_datetime(yt_df['trending_date'])
yt_df['weekday'] = yt_df['trending_date'].dt.day_name()
best_day = yt_df['weekday'].value_counts().idxmax()
print(f'Based on our trending data, the best day to post is: {best_day}')
Best Practices Review#
- Always check for missing or corrupted values in your data files.
- Aggregate metrics thoughtfully: use averages to compare typical post performance, and totals for reach.
- Be careful to define engagement metrics the same way every time.
- Use visualizations and segmentation to spot underlying trends, not just surface spikes.
- Check assumptions when comparing across platforms or time periods.
- Remember: consistent, reproducible analysis is the foundation of successful social media strategies.
Want to take your social media analytics skills to the next level?#
- Consider exploring advanced analytics like audience sentiment, share prediction, or automation using Python!
- Subscribe to our YouTube channel for in-depth tutorials and hands-on data projects.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



