NLTK and MALLET analysis of Tagging the Tower

Attribution update, November 1, 2026: Writer credits and cohort matches have been corrected from body bylines and signed contributions. Roster-subset summaries use those corrected matches. The 299-post cleaned corpus and fitted topic weights remain frozen; this is not a new NLP fit. See the source-based correction review.

Interactive companion: explore the charts, or read the interactive usage and code guide.

Both packages were actually run locally: NLTK 3.10.4 for preprocessing, frequency distributions, collocations, and concordances; MALLET 2.0.8 for five Gibbs-sampled LDA models. Python launches MALLET's official Java classes directly. No other library's LDA model is substituted for MALLET.

Cleaned corpus

The published category corpus contains 421 posts. The main model excludes 96 curated/source-linked items, 18 welcome/roster messages, and 8 posts with fewer than 30 cleaned tokens. That leaves 299 posts. Drafts and non-post items never enter this pipeline. The eight short items remain in the audit inventory; their exclusion does not mean their subject matter is unimportant.

The retained bodies contain 263,763 word tokens before stopword filtering and lemmatization, 137,094 cleaned tokens, and 123,513 tokens in the final MALLET vocabulary of 3,940 lemmas. The first count follows HTML/reference cleaning, so it is not a count of every word in the original XML. The final count additionally removes vocabulary found in fewer than three documents or at least 80% of included documents.

Cleaning strips HTML/navigation, URLs, email addresses, selected WordPress shortcodes, recognizable reference sections, and opening credit lines. NLTK applies English sentence segmentation, word tokenization, grammatical tagging, and WordNet lemmatization. The stoplist combines NLTK English stopwords with a documented custom list of site labels, markup fragments, and low-specificity terms. AI and R are retained despite their short length. No thematic dictionaries or earlier theme labels are supplied to MALLET.

The pipeline also tests for exact repeated paragraphs of at least 30 words in five or more eligible posts. It found zero after welcome-message exclusion, so it made no removals under that rule. Near-duplicate or paraphrased boilerplate can remain. Readable text is preserved separately from filtered text, including negation, for interpretive checks. Stopwords and all exclusions are supplied for review. This English-centered preprocessing is less suitable for multilingual passages and technical code; meaningful rare terms can be lost under the frequency threshold.

What NLTK adds

2026-10-31T20:59:31.624302 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Cleaned word frequencies
2026-10-31T20:59:32.009754 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Associated phrases

The associated phrases identify multiple kinds of discourse: technical methods, institutional settings, organized support, and recent conceptual concerns. The phrase analysis uses lemmatized words adjacent within sentences before stopword filtering, then filters out candidates containing excluded terms. It therefore does not create artificial phrases by joining across removed stopwords. Punctuation is removed, so lexical adjacency can span punctuation within a sentence. Candidates require at least five occurrences across three posts. The chart ranks log-likelihood association; the data also include PMI, frequency, and document counts, following the NLTK collocation workflow.

Lemmatized phraseOccurrencesPosts
open source11760
new york7948
social medium7829
text analysis7530
programming language5132
command line4626
office hour3421
york city3523
look like6343
ai literacy376
next step4123
object orient304
academic common4031
hard drive275
alt text303

The displayed “social medium,” “academic common,” and “office hour” are normalization artifacts of plural lemmatization. Counts should be interpreted as normalized expressions. PMI's highest-scoring pairs also include scholars' names; this is why a high phrase score is not automatically a substantive theme.

Concentration matters: “AI literacy” appears 37 times in six posts, while “alt text” appears 30 times in three. A concept can be salient within a small conversation without being widespread across the blog. “Open source” occurs 117 times across 60 posts, indicating a broader distribution under these rules.

2026-10-31T20:59:36.865432 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Early and recent vocabulary

Early vocabulary is relatively rich in Bootstrap, Jekyll, PHP, SQL, and WordPress; recent vocabulary includes AI, workers, LLMs, and generative systems. This combines changes in software, genre, authors, and argument. It does not mean that databases or web publishing stopped being part of fellows' work. The comparison uses smoothed relative token frequencies, not a statistical significance test, and requires at least 15 occurrences in the displayed period. Periods refer to academic-year starts: 2012–16 covers 2012–13 through 2015–16; 2024–26 covers 2024–25 and 2025–26. Partial 2026–27 is excluded from that contrast.

The supplied NLTK concordances retain context for failure, openness, labor, community, AI, refusal, and care. They help distinguish an author's endorsement from a position the post criticizes. Neither isolated word counts nor an unsupervised topic model supplies that distinction.

MALLET's eight-topic overview

Each whole post is a document. The overview uses eight topics, random seed 42, 1,000 iterations, one thread, initial total alpha 1.0, and beta 0.01. Hyperparameters are optimized every 50 iterations after a 200-iteration burn-in. The shared input and all output topic mixtures are retained. Topic weights are mixtures: 29% mean weight is not a claim that 29% of posts belong exclusively to that topic.

Labels below are human interpretations of top words and representative documents. MALLET generates numbered word distributions, not these labels. Topics 5 and 7 capture substantial general language and genre; Topic 3 combines audio with some project-support/funding vocabulary. These limitations are part of the result.

TopicInterpretive labelMean weight per postLeading words
T0Archives & text research8.3%text, data, library, collection, tool, analysis
T1AI, access & sociotechnical power8.7%ai, data, community, technology, access, human
T2Programming & structured data8.1%r, python, data, program, code, database
T3Audio practices / project support3.1%sound, audio, track, maker, record, project
T4Spatial data & visualization5.7%data, map, layer, file, color, image
T5Reflection & problem-solving language25.7%time, think, way, work, like, tool
T6Web publishing & infrastructure9.6%file, website, page, create, web, wordpress
T7Research support & community programming30.7%project, research, student, work, workshop, new
2026-10-31T20:59:35.558356 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Topic words
TopicHighest-weight exampleCredited writer(s)Topic weight
T0Working with HathiTrust Data - Part 1Param Ajmera88.6%
T1Rethinking Participatory Mapping as a Justice-Oriented PracticeParisa Setayesh84.9%
T2Reordering Graphs in ggplot Plot: A Step-by-Step GuideChen Zhou82.2%
T3Basic Audio Editing with AudacityDi Yoong76.3%
T4Using raster spatial data in RRilquer Mascarenhas81.4%
T5Think Like a Coder: Introduction to Algorithms Part 2Gregory Hartmann87.6%
T6Learn Bootstrap Part 3: Customize Bootstrap and Add a HeaderKeith Miyake95.6%
T7Digital Fellows Fall Workshops AnnouncedPatrick Sweeney95.8%

The highest-weight examples show that the model recovers recognizable methods: HathiTrust/text research, SQL and programming, Audacity/audio, spatial data, and web publishing. The highest-ranked AI/access/power examples are heavily concentrated in Parisa Setayesh's writing. This makes author specialization an essential check on any cohort interpretation.

Academic years and cohort evidence

2026-10-31T20:59:36.323248 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Academic-year topic mixtures

The AI/access/power grouping has an average post-level weight of 12.0% in 2023–24, 29.2% in 2024–25, and 29.8% in 2025–26. This supports increased prominence of sociotechnical questions in the recent texts, while also showing why the grouping cannot be read as an AI-only count: its strongest example is a participatory-mapping post.

Web publishing has relatively high weight in 2013–14 and returns in 2021–23. Programming/data is relatively prominent in 2015–18 and 2021–22. Archives/text peaks in 2019–20, including the HathiTrust series. These patterns invite investigation of author specialties and series rather than a single irreversible progression from tools to critique. The large reflective and program-support topics also indicate that publication genre matters.

Each post receives equal weight in the heatmap's annual mean, while the model itself is trained on tokens and is therefore influenced by long documents. Token-weighted annual estimates are supplied separately. Rounded rows need not total exactly 100%. Summer posts remain assigned to August–July academic years; membership confirmation still requires the earlier same-semester evidence. Partial 2026–27 has only three included posts and should not be treated as a settled trend.

2026-11-01T11:24:42.414631 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Roster-matched subset

The cohort view includes posts with at least one credited writer matched to the same-semester roster. It excludes unconfirmed writers; it does not establish that those writers were not fellows. It also includes collective posts containing both matched and unmatched writers. No author is assigned an individual share of a collective post's topic mixture. Missing early rosters severely limit that view, and no posts-per-fellow productivity rate is calculated.

2026-11-01T11:24:42.686973 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Author sensitivity

As an additional sensitivity check, removing all posts crediting Parisa Setayesh from the annual average reduces Topic 1's recent weights to 22.5% in 2024–25 and 23.7% in 2025–26. That remains above the 12.0% average in 2023–24, so the observed increase is not confined to her posts. The same-semester roster-matched averages are 31.5% and 28.1% in the two recent complete years. These are aggregation checks on the fixed model, not retrained leave-author-out models or causal estimates.

How sensitive are the topics?

The pipeline runs six-, eight-, and ten-topic models at seed 42 and repeats the eight-topic model at seeds 1729 and 99. For each model, mean document-level NPMI measures co-occurrence among its ten leading words per topic. Diversity is the fraction of unique words among those top-ten lists. These are in-sample descriptive diagnostics, not held-out predictive evaluation or validated measures of human interpretation.

TopicsSeedMean document NPMITop-ten diversity
6420.14183.3%
8420.14683.8%
10420.16187.0%
817290.13881.2%
8990.15388.8%

The ten-topic run has the highest NPMI of these trials. It separates AI/research/ethics from civic/community/access language and separates programming from databases more clearly. The eight-topic model is retained as the preselected overview, not declared optimal. Its mixtures should not be combined with ten-topic mixtures as though topic numbers had the same meaning.

2026-11-01T11:24:41.925835 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/
Seed sensitivity

The seed comparison matches topics by minimizing Jensen–Shannon distances between their full word distributions. Web publishing is the most consistent topic under that measure (mean distance about 0.206); audio/project support is the least consistent (about 0.532). The AI/access/power topic preserves the same top-ten word set in both matched seed comparisons, but its full distribution still shifts. Topic 3's audio/funding combination is particularly unsuitable for a strong historical claim. The MALLET diagnostics documentation likewise recommends inspecting topic size, coherence, and concentration rather than accepting every topic as meaningful.

Additional questions raised by this analysis

Files and reproducibility

The nlp folder contains readable and stopword-filtered per-post texts; the shared MALLET input; stoplists; a full exclusion manifest; NLTK word, phrase, contrast, and concordance tables; topic words and representative posts; document/year/cohort topic weights; model comparisons and seed matching; and PNG/SVG versions of all figures. Official MALLET diagnostics and training logs are retained for all five runs, along with the primary model and sampler state. Code resides in nlp_pipeline.py and nlp_report.py; package versions are pinned in nlp/requirements.txt. Setup instructions are in nlp/README.md.

The original XML is unchanged. All 299 document IDs match the MALLET outputs in every run; every document's topic weights sum to one; filtered text contains no listed stopwords. Corpus membership, collocation thresholds, and figure outputs are checked. This is exploratory computational evidence to accompany the earlier close readings, not a replacement for them.