Auf der Suche nach der geschätzten Lesezeit, Teil 2: Implementierung und Überprüfung.
Zusammenfassung
- Ziel: Anzeige einer Lesezeitschätzungen in meinen Blogbeiträgen, deren Berechnung über die einfache Division der Wortanzahl durch eine pauschale Lesegeschwindigkeit hinausgeht.
- Hypothese: Die Anpassung der Lesegeschwindigkeit basierend auf der durchschnittlichen Wortlänge führt zu genaueren Lesezeitschätzungen als die Verwendung einer pauschalen Lesegeschwindigkeit.
- Überprüfung: Experimente mit einer JavaScript-Implementierung der angepassten Lesegeschwindigkeit und der pauschalen Lesegeschwindigkeit widerlegen die Hypothese.
- Diskussion: Die Verwendung einer pauschalen Lesegeschwindigkeit in Wörtern pro Minute führt zu genaueren Schätzungen, die einfachere Berechnung ist daher zu bevorzugen.
Einführung & Wiederholung
Da ich mit dem Stand der Technik zur Schätzung von Lesezeiten online nicht zufrieden war, habe ich mich auf die Suche nach einem besseren Algorithmus gemacht. Basierend auf einer Literaturanalyse und einer Abwägung von Genauigkeit gegen Praktikabilität entschied ich mich für Formeln, welche die durchschnittliche Wortlänge als Indikator für die Textkomplexität berücksichtigen:
lesegeschwindigkeit_en = 238 * 4.6 / durchschnittliche_wortlaenge_des_textes
lesegeschwindigkeit_de = 185 * 5.97 / durchschnittliche_wortlaenge_des_textes
Beide Formeln basieren auf der Arbeit von Brysbaert (Brysbaert 2019). Eine viel zu detaillierte Erklärung, warum ich diese Formeln gewählt habe, steht im vorherigen Beitrag. Meine Erwartung war, dass die Verwendung einer derart angepassten Lesegeschwindigkeit genauere Schätzungen für die Lesezeit liefert.
In diesem Beitrag beschreibe ich meine Implementierung dieser Theorie und meine Erkenntnisse aus der kritischen Prüfung der Implementierung. Die Ergebnisse sind etwas ernüchternd.
Implementierung
Ich habe die Formeln in reinem JavaScript implementiert, weil das die Sprache des statischen Site-Generators ist, den ich verwende. Die Schätzung erfolgt zur Kompilierzeit und verwendet die kompilierten Blogbeiträge (d.h. HTML als String) als Eingabe.
Da die Eingabe HTML enthalten wird, benötigt die Implementierung zwei Teile: 1) Bereinigung der Eingabe und 2) Berechnung der Lesezeit.
Eingabebereinigung
Ich muss vermeiden, dass HTML-Markierungen die Wortzählung beeinflussen, daher filtere ich zuerst alle HTML-Tags aus dem Eingabestring. Außerdem nehme ich alle Satzzeichen aus dem Text. Ich verwendete dazu Textparsing basierend auf regulären Ausdrücken. Hier passiert also keine Magie.
/** Remove any HTML tags, linebreaks, punctuation or hyphens from a string
*
* For the purpose of later calculating reading rate and reading time of
* the input text.
*
* Regex used for matching HTML tags is taken from the `insane` npm library:
* https://github.com/bevacqua/insane/blob/master/parser.js#L7
*
* @param {string} inputText text to sanitize
* @returns {string} input text sans any HTML tags, linebreaks, punctuation or hyphens
*/
const sanitizeMarkup = (inputText) => {
const regexStartTag = /<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/gi;
const regexEndTag = /<\s*\/\s*([\w:-]+)[^>]*>/gi;
const regexNewLine = /[\n\r]/g;
const regexPunctuation = /[\.|\?|;|,|:|!|"|'] /g;
const regexHyphens = / - /g;
return inputText.replaceAll(regexStartTag, '')
.replaceAll(regexEndTag, '')
.replaceAll(regexNewLine, ' ')
.replaceAll(regexPunctuation, ' ')
.replaceAll(regexHyphens, ' ');
}
Berechnung der Lesezeit
Unter der Annahme, wir haben einen bereinigten Eingabestring, können wir diesen unter Verwendung von Leerzeichen als Trennzeichen aufteilen und das resultierende Array für alle weiteren Berechnungen verwenden (Wortanzahl, durchschnittliche Wortlänge usw.). Die Funktion zur Berechnung der Lesezeitschätzung akzeptiert einen optionalen Parameter, der angibt, ob die angepasste oder die pauschale Lesegeschwindigkeit verwendet werden soll. Das ist vor allem dem Umstand geschuldet, dass ich beide Berechnungsarten in meinen Tests vergleichen will.
/** Takes a text and estimates the reading time based on average reading speed of the given language.
*
* Reading speeds are taken from academic literature. You can find out more about choice of reading speeds
* here: https://auferbauer.net/en/blog/2025-04-29-2025-04-29_reading_time_estimate_part_1/
*
* You may opt to use an adjusted reading rate that takes average word length of the text vis-à-vis average
* word length of that language into account. Refer to https://doi.org/10.1016/j.jml.2019.104047
*
* @param {string} text the text for which you want to estimate reading time.
* @param {string} language the language of the text (influences assumed reading speed in words per minute); takes either 'en' or 'de', defaults to 'en'.
* @param {boolean} useAdjustedReadingRate whether you want to use an adjusted reading rate that takes average word length into account.
* @returns {number} Estimated reading time of the text in seconds.
*/
const estimateTime = (text, language, useAdjustedReadingRate) => {
if(!text || typeof text !== 'string') {
throw new Error('Text was not provided as string.');
}
let languageReadingRate = 0;
let languageAvgWordLength = 0;
switch (language) {
case 'de':
languageReadingRate = 185;
languageAvgWordLength = 5.97;
break;
case 'en':
default:
languageReadingRate = 238;
languageAvgWordLength = 4.6;
break;
}
const words = text.split(' ').filter((word) => {
let trimmed = word.trim();
return trimmed.length > 0;
});
const wordCount = words.length;
const characterTotal = words.reduce(
(characterTotal, word) => characterTotal + word.length,
0
);
const documentAvgWordLength = characterTotal / wordCount;
const adjustedReadingRate = languageReadingRate * languageAvgWordLength / documentAvgWordLength;
const readingTimeSec = (wordCount / (useAdjustedReadingRate ? adjustedReadingRate : languageReadingRate))*60;
if (process.env.NODE_ENV === 'development') {
console.debug(`Total characters: ${characterTotal}`);
console.debug(`Word count: ${wordCount}`);
console.debug(`Average word length: ${documentAvgWordLength}`);
console.debug(`Adjusted reading rate (${language}): ${adjustedReadingRate}`);
console.debug(`Estimated reading time (${language}): ${readingTimeSec} sec`);
}
return readingTimeSec;
}
Überprüfung
Meine ursprüngliche Hypothese war, dass die eingangs beschriebenen Formeln eine präzisere Schätzung der Lesezeit liefern würde. Um diese Hypothese zu testen, benötige ich eine empirische Grundlage. Die Literatur bietet einige Textsammlungen, für welche die Lesezeit gemessen wurde. Aus der englischen Literatur habe ich die folgenden verwendet:
- Frank et al. bieten Eyetracking-Daten und selbstbestimmte Lesezeiten (48 bzw. 117 Probanden) für einen Korpus englischer Sätze. Ich habe neun Sätze (insgesamt 70 Wörter) zufällig für die Auswertung ausgewählt.
- Trauzettel-Klosinski und Dietz präsentieren eine einzelne Passage aus einem standardisierten internationalen Leseverständnistest (156 Wörter) einschließlich Lesezeitstatistiken für 436 Teilnehmer.
- Siegelman et al. bieten Eyetracking-Daten aus einem internationalisierten Korpus von Textpassagen. Ich habe willkürlich Passage #9 (200 Wörter) ausgewählt und die durchschnittliche Lesezeit von 42 Teilnehmern aus den öffentlich verfügbaren Daten berechnet.
Folgendermaßen hat die von meinem Code berechnete geschätzte Lesezeit im Vergleich zu den empirischen Messungen abgeschnitten:
Korpus | Messung | Schätzung | Abweichung |
---|---|---|---|
1. | 55.02s | 51.57s | 6% |
2. | 40.4s | 37.04s | 8% |
3. | 48.15s | 53.49s | 11% |
Das ist ein anständiges Ergebnis. Die Abweichungen liegen innerhalb akzeptabler Grenzen (für meinen Zweck). Interessanterweise liefert die nicht angepasste, pauschale Lesegeschwindigkeit sogar noch bessere Ergebnisse:
Korpus | Messung | Schätzung | Abweichung |
---|---|---|---|
1. | 55.02s | 53.95s | 2% |
2. | 40.4s | 39.33s | 3% |
3. | 48.15s | 50.17s | 4% |
Das ist ein erfreuliches Ergebnis, insofern als es Funktionalität meines Codes bestätigt. Allerdings bedeutet es auch, dass mein Versuch, ein besseres Maß für die Lesgeschwindigkeit zu finden, vergeblich war.
Wie sieht es mit Lesezeitschätzungen für Deutsch aus? Es war deutlich schwieriger, Texte zu finden, die ich als empirische Grundlage für Deutsch verwenden kann. Es gibt nur zwei Quellen, für die sowohl der Text als auch die Messungen der Lesgeschwindigkeit verfügbar sind:
- Das Potsdam Text Corpus (PoTeC) enthält Eyetracking-Daten für zwölf wissenschaftliche Texte auf Deutsch (Jakobi et al., 2024).
- Der internationale Korpus von Siegelman et al., den ich bereits für die Überprüfung auf Englisch verwendet habe, bietet auch deutsche Versionen.
Ich konnte PoTeC nicht als empirische Grundlage in Betracht ziehen, da die von mir aus den Rohdaten berechneten Leseraten deutlich unter jenen lagen, die in der übrigen Literatur berichtet wurden (40 Wörter pro Minuten für manche Teilnehmer). Das ist vermutlich darauf zurückzuführen, dass ich falsch mit den Daten umgegangen bin. Unabhängig von der Ursache liegen die Werte so weit außerhalb der erwarteten Parameter, dass ich mich entschieden habe, PoTeC nicht zu verwenden.
Damit bleibt mir der Text von Siegelman et al. als einziger Datenpunkt für eine Überprüfung:
Messung | Schätzung | Abweichung |
---|---|---|
51.78s | 60.46s | 16% |
Nicht schlecht, nicht großartig. Allerdings: wie auch schon im Englischen lieferte die Verwendung einer pauschalen Leserate bessere Ergebnisse, im diesem Fall sogar noch eindeutiger:
Messung | Schätzung | Abweichung |
---|---|---|
51.78s | 54.81s | 5% |
Diskussion
Zu Beginn meiner Suche nach einer besseren Lesezeitschätzung stand die Hypothese, dass Berechnungen aufgrund einer pauschalen Lesegeschwindigkeit zu ungenauen Ergebnissen führen würden und dass es eine angepasste Lesegeschwindigkeit braucht, welche die Textkomplexität modeliert.
Überraschenderweise war dies nicht der Fall. Für alle Textkorpora, für die Lesezeitmessungen verfügbar sind, liefern Berechnungen mit einer pauschalen Lesegeschwindigkeit exaktere Ergebnisse, als unter der Verwendung der angepassten Lesegeschwindigkeit. Während die Schätzungen basierend auf der angepassten Lesegeschwindigkeit um 6%-16% von den empirischen Messungen abweichen, weichen die Schätzungen aufgrund pauschaler Lesegeschwindigkeit nur um 2%-5% ab.
Ich sehe keine Notwendigkeit, andere Ansätze zu untersuchen oder die Angelegenheit noch weiter unnötig kompliziert zu machen. Die pauschale Lesegeschwindigkeit basierend auf Wörtern pro Minute ist das robustere Werkzeug zur Schätzung der Lesezeit und funktioniert mehr als zufriedenstellend.
Der Code, den ich verwendet habe, um meine Hypothese zu überprüfen, ist daher nicht besser oder schlechter als der meiste andere Code zur Schätzung der Lesezeit, den man im Internet findet. Zum Zeitpunkt der Veröffentlichung dieses Beitrages verwende ich meinen Code, um die Lesezeiten auf diesem Blog zu schätzen. Damit kommt meine Suche nach der Schätzung der Lesezeit zu einem Ende. Letztendlich trifft das KISS-Prinzip wieder einmal zu.
Wir lesen uns im nächsten Beitrag!