Analyzing YouTube Channel Using Python
YouTube has become one of the most powerful platforms for storytelling, education, interviews, and community building. For this Python project, I analyzed the Lynn Ngugi YouTube channel using data collected from the YouTube Data API.
The goal of this project was to understand how the channel performs based on key engagement metrics such as:
- Subscribers
- Total views
- Number of uploaded videos
- Video views
- Likes
- Comments
- Monthly publishing patterns
I used Python libraries such as pandas, seaborn, and matplotlib to collect, clean, analyze, and visualize the data.
Project Objective
The main objective of this project was to answer the following questions:
- How does Lynn Ngugi’s channel compare with similar Kenyan YouTube channels?
- Which Lynn Ngugi videos have the highest views?
- Which videos received the most likes?
- Which videos generated the most comments?
- What months had the highest number of published videos?
Tools Used
For this analysis, I used:
from googleapiclient.discovery import build
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatterThe main tools were:
- YouTube Data API for collecting channel and video data
- pandas for data cleaning and analysis
- seaborn for visualizations
- matplotlib for plot formatting
Connecting to the YouTube Data API
I started by connecting Python to the YouTube Data API.
api_key = "YOUR_API_KEY"
channel_ids = [
"UCa2gldA2ivhzMwIJRA5683w", # Lynn Ngugi
"UCAvd919a1ibeG5cp5QtwXOw", # Shared Moments with Justus
"UCVdwlgozebl0aSoYStxUlyA", # Metha ya Kagoni
"UCl6ICaB9meBcSMQ5Zmr446g" # Tuko / Tuco - Kenya
]
youtube = build("youtube", "v3", developerKey=api_key)I included Lynn Ngugi and a few related Kenyan YouTube channels for comparison.
Getting Channel Statistics
Next, I created a function to collect channel-level statistics.
def get_channel_stats(youtube, channel_ids):
all_data = []
request = youtube.channels().list(
part='snippet, contentDetails, statistics',
id=','.join(channel_ids)
)
response = request.execute()
for i in range(len(response['items'])):
data = dict(Channel_name=response['items'][i]['snippet']['title'],
Subscribers=response['items'][i]['statistics']['subscriberCount'],
Views=response['items'][i]['statistics']['viewCount'],
Total_videos=response['items'][i]['statistics']['videoCount'],
playlist_id = response['items'][i]['contentDetails']['relatedPlaylists']['uploads'])
all_data.append(data)
return all_dataThen I converted the result into a pandas DataFrame.
channel_statistics = get_channel_stats(youtube, channel_ids)
channel_data = pd.DataFrame(channel_statistics)
channel_dataFrom this output, Lynn Ngugi had 149,000 subscribers, 190,885,305 total views, and 605 uploaded videos at the time of data collection.
Cleaning the Channel Data
The data from the API came in as text, so I converted the numeric columns into integers.
channel_data.dtypeschannel_data['Subscribers']=pd.to_numeric(channel_data['Subscribers'])
channel_data['Views']=pd.to_numeric(channel_data['Views'])
channel_data['Total_videos']=pd.to_numeric(channel_data['Total_videos'])
channel_data.dtypes
Visualizing Subscribers by Channel
I created a bar chart to compare subscribers across the channels.
# Create the bar plot
plt.figure(figsize=(10, 6))
ax = sns.barplot(x='Channel_name', y='Subscribers', data=channel_data)
# Function to format y-axis labels in millions or thousands
def format_func(value, tick_number):
if value >= 1e6:
return '{:.0f}M'.format(value * 1e-6)
elif value >= 1e3:
return '{:.0f}K'.format(value * 1e-3)
else:
return int(value)
# Apply the formatter to the y-axis
ax.yaxis.set_major_formatter(FuncFormatter(format_func))
# Add text labels on the bars
for p in ax.patches:
ax.annotate(f"{int(p.get_height()):,}", # Using f-string to format the number with commas
(p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center', fontsize=10, color='black', xytext=(0, 5),
textcoords='offset points')
ax.set_title('Subscribers of YouTube Channels')
ax.set_xlabel('Channel Names')
ax.set_ylabel('Number of Subscribers')
ax.tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()Lynn Ngugi has the highest subscribers (1.49M), followed by Tuko Tuko Kenya (1.21M). Metha Ya Kagoni has moderate subscribers (375K), while Shared Moments with Justus has the lowest (178K). This shows a clear gap between top and smaller channels.
Visualizing Total Views by Channel
I also compared total views across the channels.
# Create the bar plot
plt.figure(figsize=(10, 6))
ax = sns.barplot(x='Channel_name', y='Views', data=channel_data)
# Function to format y-axis labels in millions or thousands
def format_func(value, tick_number):
if value >= 1e6:
return '{:.0f}M'.format(value * 1e-6)
elif value >= 1e3:
return '{:.0f}K'.format(value * 1e-3)
else:
return int(value)
# Apply the formatter to the y-axis
ax.yaxis.set_major_formatter(FuncFormatter(format_func))
# Add text labels on the bars
for p in ax.patches:
ax.annotate(f"{int(p.get_height()):,}", # Using f-string to format the number with commas
(p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center', fontsize=10, color='black', xytext=(0, 5),
textcoords='offset points')
ax.set_title('Views of YouTube Channels')
ax.set_xlabel('Channel Names')
ax.set_ylabel('Number of Views')
ax.tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()Tuko Tuko Kenya has the highest views (268.7M), followed by Lynn Ngugi (190.9M). Metha Ya Kagoni has moderate views (79.4M), while Shared Moments with Justus has the lowest (20.9M). This shows a strong lead by the top channels.
Visualizing Total Videos by Channel
Next, I compared the total number of uploaded videos.
plt.figure(figsize=(10, 6))
ax = sns.barplot(x='Channel_name', y='Total_videos', data=channel_data)
# Add text labels on the bars
for p in ax.patches:
ax.annotate(f"{int(p.get_height()):,}", # Using f-string to format the number with commas
(p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center', fontsize=10, color='black', xytext=(0, 5),
textcoords='offset points')
ax.set_title('Total Videos of YouTube Channels')
ax.set_xlabel('Channel Names')
ax.set_ylabel('Number of Total Videos')
ax.tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()Metha Ya Kagoni has the highest number of videos (2,552), followed by Tuko Tuko Kenya (2,102). Shared Moments with Justus has 798 videos, while Lynn Ngugi has the fewest (605). This shows that posting more videos does not always mean higher subscribers or views. Although Lynn Ngugi had fewer uploaded videos than some comparison channels, the channel still had a very high number of views. This suggests strong performance per video.
Getting Lynn Ngugi’s Upload Playlist ID
To analyze individual videos, I first extracted Lynn Ngugi’s upload playlist ID.
playlist_id = channel_data.loc[
channel_data["Channel_name"] == "Lynn Ngugi",
"playlist_id"
].iloc[0]This playlist ID was then used to collect video IDs from the channel.
Getting Video IDs
I created a function to collect all video IDs from Lynn Ngugi’s uploads playlist.
def get_video_ids(youtube, playlist_id):
request = youtube.playlistItems().list(
part="contentDetails",
playlistId=playlist_id
)
response = request.execute()
video_ids = []
for i in range(len(response["items"])):
video_ids.append(response["items"][i]["contentDetails"]["videoId"])
next_page_token = response.get("nextPageToken")
more_pages = True
while more_pages:
if next_page_token is None:
more_pages = False
else:
request = youtube.playlistItems().list(
part="contentDetails",
playlistId=playlist_id,
maxResults=50,
pageToken=next_page_token
)
response = request.execute()
for i in range(len(response["items"])):
video_ids.append(response["items"][i]["contentDetails"]["videoId"])
next_page_token = response.get("nextPageToken")
return video_idsThen I ran:
video_ids = get_video_ids(youtube, playlist_id)Getting Video-Level Details
After collecting the video IDs, I created another function to get details for each video.
def get_video_details(youtube, video_ids):
all_video_stats = []
for i in range(0, len(video_ids), 50):
request = youtube.videos().list(
part='snippet, statistics',
id=','.join(video_ids[i:i+50]))
response = request.execute()
for video in response['items']:
video_stats = {
'Title': video['snippet']['title'],
'Published_date': video['snippet']['publishedAt'],
'Views': video['statistics']['viewCount'],
'Likes': video['statistics']['likeCount'],
'Comments': video['statistics']['commentCount']
}
all_video_stats.append(video_stats)
return all_video_statsI converted the result into a DataFrame.
video_details = get_video_details(youtube, video_ids)
video_data = pd.DataFrame(video_details)
video_data.head()Cleaning the Video Data
I cleaned the date and converted the numeric columns.
video_data['Published_date'] = pd.to_datetime (video_data['Published_date']).dt.date
video_data['Views'] = pd.to_numeric(video_data['Views'])
video_data['Likes']= pd.to_numeric(video_data['Likes'])
video_data['Comments'] = pd.to_numeric(video_data['Comments'])
video_data['Views'] = pd.to_numeric(video_data['Views'])Top 10 Videos by Views
I sorted the videos by views to find the most viewed videos.
top10_videos = video_data.sort_values(
by="Views",
ascending=False
).head(10)
top10_videosplt.figure(figsize=(10, 6))
ax = sns.barplot(x='Views', y='Title', data=top10_videos)
ax.set_title('Top 10 Videos by Views')
ax.set_xlabel('Views')
ax.set_ylabel('Video Title')
plt.tight_layout()
plt.show()The most viewed video had over 2 million views. A key observation is that many of the most viewed videos focused on deeply personal stories, relationships, grief, survival, and emotionally intense life experiences. This suggests that Lynn Ngugi’s audience strongly connects with human-interest storytelling.
Bottom 10 Videos by Views
I also looked at the videos with the lowest views.
bottom10_videos = video_data.sort_values(
by="Views",
ascending=False
).tail(10)
bottom10_videosplt.figure(figsize=(10, 6))
ax = sns.barplot(x='Views', y='Title', data=bottom10_videos)
ax.set_title('Bottom 10 videos by Views')
ax.set_xlabel('Views')
ax.set_ylabel('Video Title')
plt.tight_layout()
plt.show()Even the lower-view videos still had thousands of views, showing that the channel maintained a steady audience base.
Top 10 Videos by Likes
Next, I analyzed videos with the highest number of likes.
top10_liked_videos = video_data.sort_values(
by="Likes",
ascending=False
).head(10)Then I visualized them.
plt.figure(figsize=(10, 6))
ax = sns.barplot(
x="Likes",
y="Title",
data=top10_liked_videos
)
ax.set_title("Top 10 Videos by Likes")
ax.set_xlabel("Likes")
ax.set_ylabel("Video Title")
plt.tight_layout()
plt.show()Likes are useful because they show direct positive audience response. Videos with high likes may not only be widely watched, but also emotionally meaningful to viewers.
Top 10 Videos by Comments
I also analyzed the videos with the most comments.
top10_commented_videos = video_data.sort_values(
by="Comments",
ascending=False
).head(10)Then I visualized the results.
plt.figure(figsize=(10, 6))
ax = sns.barplot(
x="Comments",
y="Title",
data=top10_commented_videos
)
ax.set_title("Top 10 Videos by Comments")
ax.set_xlabel("Comments")
ax.set_ylabel("Video Title")
plt.tight_layout()
plt.show()Comments are especially important for a storytelling channel because they show conversation, emotional response, and audience involvement. One video in the top-viewed list had 14,127 comments, while another had 12,570 comments. This shows that some videos did more than attract viewers; they created strong audience discussion.
Publishing Pattern by Month
To understand upload patterns, I extracted the month from each video’s published date.
video_data["Month"] = pd.to_datetime(
video_data["Published_date"]
).dt.strftime("%b")videos_per_month = video_data.groupby(
"Month",
as_index=False
).size()
videos_per_monthVisualizing Videos Published per Month
palette = sns.color_palette("husl", len(videos_per_month["Month"]))
plt.figure(figsize=(10, 6))
sns.barplot(
x="Month",
y="size",
data=videos_per_month,
palette=palette
)
plt.title("Number of Videos Published per Month")
plt.xlabel("Month")
plt.ylabel("Number of Videos")
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()The months with the highest number of published videos were:
- November: 62 videos
- September: 62 videos
- December: 51 videos
- October: 57 videos
This shows that the channel had strong publishing activity toward the end of the year.
Key Findings
From this Python analysis, I found that:
- Lynn Ngugi had 1,490,000 subscribers at the time of data collection.
- The channel had over 190,885,305 total views.
- The dataset contained 605 videos from Lynn Ngugi’s channel.
- The most viewed video had over 2 million views.
- Videos with emotional, personal, and human-interest stories appeared among the highest-performing videos.
- Some videos generated very high comment activity, showing strong audience engagement.
- November and September had the highest number of published videos, with 62 videos each.
Conclusion
This project showed how Python can be used to collect and analyze real-world social media data.
Get Diana Opiyo’s stories in your inbox
Join Medium for free to get updates from this writer.
Using the YouTube Data API, I was able to collect channel statistics and video-level performance data. With pandas, I cleaned and organized the data. With seaborn and matplotlib, I created visualizations to compare subscribers, views, uploads, likes, comments, and monthly publishing patterns.
The analysis showed that Lynn Ngugi’s channel has strong audience reach and engagement. The most successful videos were not just high in views; many also had high likes and comments, suggesting that storytelling and emotional connection are major drivers of engagement on the channel.
For future work, I would extend this analysis by adding:
- Sentiment analysis of YouTube comments
- Topic modeling of video titles
- Engagement rate calculations
- Trend analysis over time
- Comparison of views per video across similar channels
This would give a deeper understanding of what type of content performs best and how audience engagement changes over time.








