All Data Labs

Machine learning

Learner Personas with Clustering

medium3–4 hours1 dataset
Company
Duolingo
Job positions
Data ScientistProduct AnalystData Analyst
Topics
ClusteringK-meansFeature scalingUnsupervised learningProduct analytics

The scenario

Duolingo: Use clustering to discover the kinds of learners using the app, and turn each group into a persona the product team can act on.

Duolingo's growth team sends the same reminders and offers to every learner. But some people practice for five minutes every morning, others binge on Sundays, and some cram before a trip and then disappear. The team wants to understand the kinds of learners it actually has so each group gets the right nudge. You're a data scientist on the learning insights team.

Your task

Group learners by how they use the app with clustering, describe each group as a persona the product team can act on, and assign every learner to a group.

Instructions

  1. 1Explore the behavior columns: their distributions, skew, missing values and correlations. Look for accounts whose activity no person could produce.
  2. 2Prepare the features: handle missing values and the unusual accounts, transform skewed columns, and scale everything so no single column dominates. Explain each choice.
  3. 3Run k-means for a range of cluster counts, and choose one using the elbow method, silhouette scores and whether the groups make sense.
  4. 4Try a second method, such as hierarchical clustering or a Gaussian mixture model, and compare it with k-means.
  5. 5Profile each cluster: its size, typical values for the key behaviors and what sets it apart. Give each one a short persona name.
  6. 6Recommend one product action for each persona, such as a different reminder time or offer, and a metric to test it with.
  7. 7Save clusters.csv with the columns learner_id and cluster for every learner in learners.csv.

Datasets

All files come in one download.

learners.csv

6,000 learners with their app activity over the last 90 days.

6,000 rows · 18 columns · 505 KB

ColumnTypeDescription
learner_idtextUnique ID of the learner.
signup_datedateDate the learner created an account.
countrytextLearner's country.
platformtextDevice used most: android, ios or web.
courses_activeintegerNumber of language courses in progress.
subscriptiontextfree or super.
days_active_last_30integerDays with at least one lesson in the last 30 days.
sessions_per_weekdecimalAverage practice sessions per week.
avg_session_minutesdecimalAverage length of a session, in minutes.
longest_streak_daysintegerLongest run of consecutive days practiced.
lessons_completed_90dintegerLessons completed in the last 90 days.
xp_earned_90dintegerExperience points earned in the last 90 days.
share_sessions_weekenddecimalShare of sessions on Saturday or Sunday.
share_sessions_morningdecimalShare of sessions before noon, local time.
leaderboard_weeks_joinedintegerWeeks the learner took part in the weekly leaderboard, out of the last 13.
share_lessons_new_contentdecimalShare of lessons that taught new material rather than reviewing old material.
days_since_last_activeintegerDays since the learner last practiced.
notifications_enabledtextWhether reminders are turned on: yes or no.
Preview the first 5 rows
learner_idsignup_datecountryplatformcourses_activesubscriptiondays_active_last_30sessions_per_weekavg_session_minuteslongest_streak_dayslessons_completed_90dxp_earned_90dshare_sessions_weekendshare_sessions_morningleaderboard_weeks_joinedshare_lessons_new_contentdays_since_last_activenotifications_enabled
L1000012025-06-13United Statesandroid1super163.1empty30862130390.390.6670.160yes
L1000022024-07-13Indiaandroid2free111.37.92923641510.420.1900.7216yes
L1000032025-04-14Mexicoandroid2free144.4111.7715226470.66000.668no
L1000042024-01-22Brazilios1super308.723.4133548110930.630.43130.480yes
L1000052024-01-22Indiaios1free66.68738613900.870.1400.740yes

Hints

K-means works on distances, so a column measured in thousands, like xp_earned_90d, outweighs a share between 0 and 1 unless you scale. Taking the log first tames long tails.

import numpy as np
from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(np.log1p(features))

A handful of extreme accounts can pull a k-means center toward them. Decide how to treat them before you cluster, and give them their own label in clusters.csv if you set them aside.

Deliverable

A public GitHub repo with your notebook or scripts, clusters.csv assigning every learner to a cluster, and a README with persona profiles, supporting charts and your recommendations.

When you're done, post your repo in the Solutions tab to share it with other learners.

What grading checks

Use this checklist to review your own work before you post and share it.

  • Submitted GitHub repo is public and reachable.
  • Repo contains at least one notebook or script file.
  • clusters.csv assigns a cluster to all 6,000 learners.
  • Clusters agree with the behavior patterns the learners were drawn from, with an adjusted Rand index of at least 0.70.
  • Scaling, skewed columns and unusual accounts are handled, with each choice explained.
  • Each cluster is profiled with its size, key behaviors and a persona name.
  • Each persona has a product recommendation and a metric to test it.