Skip to content
academia.sh

Lesson 02 / 24

User Profiles

That a persona is not a fabricated person but a behavior set derived from data; clustering participants, calculating the explanatory power of role-based grouping, and the ethical limit of a persona.

Contents

The previous lesson pulled ten codes out of twelve interviews, but still left the participants as a list in the form P01P12. No design decision can be made with this list: twelve separate people do not get twelve separate interfaces. Seeing the list’s structure is necessary to make a decision — who resembles whom, along which axis, and does that axis change the design?

The common answer to this question is wrong. Participants are usually grouped by role: undergraduate student, graduate student, faculty member, library staff member, external member. This grouping looks manageable because roles are already on record. This lesson compares two groupings on the same data and calculates how much of the behavior role actually explains.

What a Persona Is and Is Not

A persona is a definition derived from research data that represents a set of behaviors. It has three parts:

  • Goal: the reason the person uses the interface. “Browsing sources” and “finding a known book” are separate goals, and they produce separate interface decisions.
  • Behavior: the observed form of the goal. Session duration, search type, borrowing frequency, which screen they entered from.
  • Constraint: conditions the person cannot change. Time, screen, language, accessibility requirement.

When a persona contains anything outside these three, it stops producing design decisions. A made-up name, an age, a photograph, and a life story try to make the persona look “alive,” but no decision can be grounded in these details. In the catalog interface, the decision of how many rows the result list shows depends on whether the user’s session lasts four minutes or twenty-two, not on whether the user is thirty-two or forty-five years old.

The criterion is this: a design decision must be demonstrable for every line written in the persona. A line with no corresponding decision is removed from the persona.

Clustering Participants by What Is Measured

Four measures were extracted from the observation sessions: the share of a session spent on subject browsing, the average session duration, the monthly borrow count, and the share of sessions entered from a narrow screen. Because these measures are on different scales, they are first moved into a common range, then the distance between participants is calculated, and the ones close to each other are merged.

// profile.mjs — comparing grouping by behavior with grouping by role

// Measures derived from observation sessions (data constructed for this lesson).
// browse: share of session spent on subject browsing, duration: average session minutes,
// borrows: monthly borrow count, narrowScreen: share of sessions on a narrow screen.
const PARTICIPANTS = [
  { id: "P01", role: "undergraduate", browse: 0.15, duration: 4,  borrows: 6, narrowScreen: 0.10 },
  { id: "P02", role: "graduate",      browse: 0.85, duration: 22, borrows: 2, narrowScreen: 0.20 },
  { id: "P03", role: "undergraduate", browse: 0.45, duration: 6,  borrows: 2, narrowScreen: 0.85 },
  { id: "P04", role: "undergraduate", browse: 0.80, duration: 19, borrows: 3, narrowScreen: 0.15 },
  { id: "P05", role: "faculty",       browse: 0.20, duration: 5,  borrows: 8, narrowScreen: 0.05 },
  { id: "P06", role: "external",      browse: 0.50, duration: 7,  borrows: 1, narrowScreen: 0.90 },
  { id: "P07", role: "staff",         browse: 0.40, duration: 5,  borrows: 3, narrowScreen: 0.80 },
  { id: "P08", role: "staff",         browse: 0.10, duration: 3,  borrows: 7, narrowScreen: 0.15 },
  { id: "P09", role: "faculty",       browse: 0.90, duration: 25, borrows: 2, narrowScreen: 0.10 },
  { id: "P10", role: "graduate",      browse: 0.48, duration: 8,  borrows: 2, narrowScreen: 0.88 },
  { id: "P11", role: "external",      browse: 0.78, duration: 20, borrows: 1, narrowScreen: 0.25 },
  { id: "P12", role: "graduate",      browse: 0.18, duration: 5,  borrows: 6, narrowScreen: 0.12 },
];
const MEASURES = ["browse", "duration", "borrows", "narrowScreen"];

// Measures are on different scales; move each into the 0-1 range.
const min = {}, max = {};
for (const m of MEASURES) {
  min[m] = Math.min(...PARTICIPANTS.map((p) => p[m]));
  max[m] = Math.max(...PARTICIPANTS.map((p) => p[m]));
}
const vector = (p) => MEASURES.map((m) => (p[m] - min[m]) / (max[m] - min[m]));
const V = PARTICIPANTS.map(vector);
const distance = (a, b) => Math.hypot(...a.map((v, i) => v - b[i]));

// Agglomerative clustering with complete linkage: merge the two nearest clusters, stop at k clusters.
function cluster(target) {
  let clusters = V.map((_, i) => [i]);
  while (clusters.length > target) {
    let best = [0, 1], smallest = Infinity;
    for (let i = 0; i < clusters.length; i++)
      for (let j = i + 1; j < clusters.length; j++) {
        let d = 0;
        for (const a of clusters[i]) for (const b of clusters[j]) d = Math.max(d, distance(V[a], V[b]));
        if (d < smallest) { smallest = d; best = [i, j]; }
      }
    const [i, j] = best;
    clusters = clusters.filter((_, x) => x !== i && x !== j).concat([clusters[i].concat(clusters[j])]);
  }
  return clusters.map((c) => c.sort((a, b) => a - b)).sort((a, b) => a[0] - b[0]);
}

// Within-cluster sum of squares: each member's squared distance to the cluster mean
const sumOfSquares = (groups) =>
  groups.reduce((t, g) => {
    const avg = MEASURES.map((_, d) => g.reduce((s, i) => s + V[i][d], 0) / g.length);
    return t + g.reduce((s, i) => s + distance(V[i], avg) ** 2, 0);
  }, 0);

const TOTAL = sumOfSquares([PARTICIPANTS.map((_, i) => i)]);
const roleGroups = [...new Set(PARTICIPANTS.map((p) => p.role))].map((r) =>
  PARTICIPANTS.map((p, i) => [p, i]).filter(([p]) => p.role === r).map(([, i]) => i)
);
const behaviorGroups = cluster(3);

console.log("clusters by behavior (k = 3)");
for (const g of behaviorGroups) {
  const avg = MEASURES.map((_, d) => g.reduce((s, i) => s + PARTICIPANTS[i][MEASURES[d]], 0) / g.length);
  console.log(
    `  ${g.map((i) => PARTICIPANTS[i].id).join(" ").padEnd(20)} n=${g.length}  ` +
      `browse ${avg[0].toFixed(2)}  duration ${avg[1].toFixed(1)} min  borrows ${avg[2].toFixed(1)}  narrow screen ${avg[3].toFixed(2)}`
  );
  console.log(`     roles: ${[...new Set(g.map((i) => PARTICIPANTS[i].role))].sort().join(", ")}`);
}

console.log("\ngroups by role");
for (const g of roleGroups) {
  console.log(`  ${PARTICIPANTS[g[0]].role.padEnd(14)} ${g.map((i) => PARTICIPANTS[i].id).join(" ").padEnd(16)} n=${g.length}`);
}

const roleSS = sumOfSquares(roleGroups), behaviorSS = sumOfSquares(behaviorGroups);
console.log("\ngrouping          groups  within-cluster sum of squares  explained variance");
console.log(`by role           ${String(roleGroups.length).padStart(6)}  ${roleSS.toFixed(3).padStart(28)}  ${((1 - roleSS / TOTAL) * 100).toFixed(1)}%`);
console.log(`by behavior       ${String(behaviorGroups.length).padStart(6)}  ${behaviorSS.toFixed(3).padStart(28)}  ${((1 - behaviorSS / TOTAL) * 100).toFixed(1)}%`);
console.log(`total variance (single group): ${TOTAL.toFixed(3)}`);

// Each cluster's medoid: the member whose distance sum within the cluster is smallest
console.log("\ncluster  medoid  within-cluster distance sum");
for (const g of behaviorGroups) {
  const scores = g.map((i) => [i, g.reduce((s, j) => s + distance(V[i], V[j]), 0)]);
  scores.sort((a, b) => a[1] - b[1]);
  console.log(`${g.map((i) => PARTICIPANTS[i].id).join("+").padEnd(20)} ${PARTICIPANTS[scores[0][0]].id}  ${scores[0][1].toFixed(3)}`);
}
clusters by behavior (k = 3)
  P01 P05 P08 P12      n=4  browse 0.16  duration 4.3 min  borrows 6.8  narrow screen 0.11
     roles: faculty, graduate, staff, undergraduate
  P02 P04 P09 P11      n=4  browse 0.83  duration 21.5 min  borrows 2.0  narrow screen 0.17
     roles: external, faculty, graduate, undergraduate
  P03 P06 P07 P10      n=4  browse 0.46  duration 6.5 min  borrows 2.0  narrow screen 0.86
     roles: external, graduate, staff, undergraduate

groups by role
  undergraduate  P01 P03 P04      n=3
  graduate       P02 P10 P12      n=3
  faculty        P05 P09          n=2
  external       P06 P11          n=2
  staff          P07 P08          n=2

grouping          groups  within-cluster sum of squares  explained variance
by role                5                         4.885  22.3%
by behavior            3                         0.261  95.8%
total variance (single group): 6.286

cluster  medoid  within-cluster distance sum
P01+P05+P08+P12      P01  0.538
P02+P04+P09+P11      P02  0.605
P03+P06+P07+P10      P03  0.450

Role Is Not a Persona

The result of the comparison reads in a single line. Grouping by role produces five groups and explains 22.3% of the variance in behavior; grouping by behavior explains 95.8% with three groups. This comparison favors role, because more groups always tend to produce smaller within-group variance. Higher explanation with fewer groups shows that the difference comes from the data.

The reason shows up in the composition of the clusters: each of the three behavior clusters contains four distinct roles. Two people with the same role do not resemble each other; four people with different roles do. Undergraduate P01 and faculty member P05 are in the same cluster — both want to find a known record and leave. Undergraduate P04 and faculty member P09 are in another cluster — both browse by subject. Role is cheap to measure because it is already written in the library record; it has no counterpart in design because it does not explain behavior.

The averages of the three clusters give the core of the personas.

  • Known-Record Searcher. Subject-browsing share 0.16, session 4.3 minutes, 6.8 borrows a month. For this persona, the first row of the result list is decisive; the user does not scan the list, they confirm the first match and leave.
  • Subject Browser. Subject-browsing share 0.83, session 21.5 minutes, 2.0 borrows a month. This persona actually reads the list, compares, and leaves without borrowing in most sessions. What matters to them is not the transaction but being able to return to the list.
  • Narrow-Screen Viewer. 0.86 of sessions on a narrow screen, duration 6.5 minutes. This persona’s constraint is the screen: the same result list shows them fewer rows, and the same action bar does not fit.

The third table gives each cluster’s medoid: the member whose within-cluster distance sum is smallest. When the persona text is written, this participant’s notes are used, because it is a real record standing at the center of the cluster. It is not an average person; it is the person closest to the average.

The Ethical Limit of a Persona

Because a persona is derived from research data, it inherits every obligation that participant data carries.

A single-member cluster is not a persona. If a cluster reduces to a single member, that persona is one person’s behavior record; even with the name removed, someone on the team recognizes it. The rule is this: if a persona does not represent the behavior of at least three participants, it is not written as a persona — it stays an observation. All three clusters above have four members.

The medoid’s quote is anonymized too. When a participant’s words are brought into the persona text, details that would make the person identifiable are removed. The criterion set in the previous lesson applies here as well: it must not be possible to trace back from the data to identity.

The persona stays within the scope of consent. When the participant joined the research, they consented to their data being used in design decisions, not to their name appearing on a persona card. This is the only defensible reason for giving personas made-up names, but the made-up name is also chosen so that it does not evoke the real one.

A persona must not turn into a tool for exclusion. The sentence “this persona is not our user” can be written as a scope decision, but it is written together with who was not measured. If none of the three personas were derived from a participant who uses a screen reader, that is not a finding but a sample gap, and it is recorded in the persona document as such.

Summary

  • A persona is the triad of goal, behavior, and constraint; a design decision must be demonstrable for every line in the persona.
  • Participants are clustered by measured behavior; the measures are moved into a common range and merged by distance.
  • In the sample data, grouping by role explained 22.3% of the variance with five groups, and grouping by behavior explained 95.8% with three groups; role is cheap to measure but does not explain behavior.
  • Each cluster’s medoid is the real participant whose within-cluster distance sum is smallest; the persona text is written from this record, not from an average person.
  • A persona is not written unless it represents at least three participants; a persona must not make a participant re-identifiable, and it must not present those left outside the sample as a finding.

Next Step

Three personas were obtained, but a persona alone is not a to-do list. The Subject Browser persona’s session lasts twenty-one minutes — what exactly do they do in that time, which steps do they follow in order, and what should be expected at each step? The next lesson turns the need into action: it addresses the form in which a user story is written, how a solution seeps into it, and how tasks are ranked by frequency and failure data.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close