Digital resources in the Social Sciences and Humanities OpenEdition Our platforms OpenEdition Books OpenEdition Journals Hypotheses Calenda Libraries OpenEdition Freemium Follow us

Behind the Counter: Topic Modelling — A Compass, Not a Substitute

For a historian seeking to understand what it meant to be a shopkeeper in late Qing-Republican Shanghai through a corpus of articles extracted from the Shenbao (1872-1949), the main challenge is to figure out what to read. In the previous blog posts, we have approached shopkeepers from various angles, almost all of them through data transformed from the metadata that each article carries with it. Collocation has already brought us close to the language that was used about shopkeepers. Yet even collocation remains at a high level of abstraction as it loses the connection with the original stories in the articles. Firsthand reading remains a fundamental prerequisite to proceed with a serious analysis. With a corpus of 69,000 articles, the question becomes: what should I read?

Even without such a massive corpus, the question has no straightforward answer.  It is not about quantity. It is about the objective of the research. It is about the research question. What to read depends heavily on one’s specific interest beyond knowing more about shopkeepers. In my initial blog post, I raised the following questions to define the main directions of my research: How did the press describe “shopkeepers” (店主, 掌柜, 商戶, and other terms)? In what contexts did they appear—as economic actors, civic leaders, troublemakers, or victims? What connotations did these labels carry? There was clearly a bias toward the “public discourse’” on shopkeepers. This will do for now, even if I intend to move my line of inquiry toward an exploration of the everyday life and social aspects of shopkeepers.

Topic modeling is precisely one of the methods that best apply to the study of discourses. On the one hand, I use this method to analyze the main trends in press articles about a given topic. Topic modeling is a computational method that automatically identifies recurring themes in a large collection of texts by detecting patterns of words that frequently occur together. This is exactly what I want to do about my press corpus on shopkeepers. On the other hand, topic modeling can also be used in refining the set of articles selected for close reading. It is not a magical tool. It will not point to the articles to be read. First, it will define the main topics that dominate in the corpus. For instance, it may group a whole group of articles under a “classified ads” topic, in which I have zero interest (but someone else could). Depending on what I am interested in, I can filter the topics and look more precisely into those with a direct relevance to my research question. Second, topic modeling produces “topic proportion” indices for each topic and each article. One can use these figures to select the articles in which a given topic is highly represented. Again, this is not absolute science, but it provides a reasonable compass for selecting articles than random reading as was the practice — inevitably — before.

In the next paragraphs, I will first briefly explain how topic modeling works, which specific methods I have used, and describe the workflow. From there, I will move to presenting various outputs from this approach, mostly visualizations, which I used for my analysis. Yet, I want to emphasize again that visualizations are the public face of a whole statistical apparatus which provides the solid ground on which I build my analysis of public discourse on shopkeepers. In the final section of this blog post, I turn data and visualizations into a historical narrative and interpretation.

How topic modeling works, and what I did with it

At its simplest, topic modeling is a way of getting a machine to read a large pile of documents and propose, statistically rather than semantically, what they tend to talk about. It does not know Chinese history, and it does not know what a shopkeeper is. What it knows is co-occurrence: which words tend to show up in the same documents as which other words, across the whole corpus at once. Words that cluster together — 捕房, 捕頭, 洋銀, 公堂 — get bundled into a “topic,” and every document is described not as belonging to one topic but as a mixture of all of them, in different proportions. A short court notice might be 90% “police blotter” and 10% everything else; a long feature article might spread itself across five or six topics at once. That mixture-of-topics-per-document is the actual output I work with — not a label, but a vector of proportions, one number per topic, summing to 1 for every article.

The specific method I used is Structural Topic Modeling (STM), an extension of the more familiar Latent Dirichlet Allocation (LDA) that lets topic prevalence — how much of a topic shows up — vary systematically with document metadata. In my case, that covariate is Year. This matters for a newspaper corpus that runs from 1872 to 1949: shopkeepers didn’t disappear from crime reporting in 1920 because the model decided to look elsewhere, they disappeared because the actual mix of what got written about them changed, and STM is built to let me estimate and plot that year-by-year drift directly rather than treat every document as historically interchangeable, as plain LDA would.

From raw text to a model: the workflow

The corpus that goes into the model — I call it shopTM in the scripts — is not the same 69,000-article corpus discussed in the earlier posts in this series. It is a cleaned, tokenized, and trimmed version of it, built specifically for topic modeling, and it is worth being explicit about every step that got it there, since each one is a methodological choice, not a neutral default:

  • Deduplication. Some articles in the original corpus had been split into multiple records sharing a base document ID (an artifact of how the OCR/segmentation pipeline occasionally broke a single article into pieces); I kept only the first occurrence of each base ID.
  • Cleaning. Leading punctuation and irregular whitespace were stripped, and four documents with known encoding corruption were dropped outright.
  • Filtering to Chinese-script content. Documents with no detectable Chinese characters were removed — mostly OCR noise, not real articles.
  • Boilerplate removal. A handful of near-universal, near-meaningless tokens (先生, 昨日, 無名氏, Chinese numerals, and two brand-name normalizations — 本公司→公司, 本銀行→銀行) were stripped before modeling, so they wouldn’t dominate every topic equally without discriminating between any of them.
  • Stopword removal. A large custom list of Chinese function words and stock newspaper phrases (roughly 1,100 entries) was removed, on top of stm’s own English-stopword pass — the latter mostly catches stray Latin-script filler in this corpus, since the text is otherwise Chinese.
  • Tokenization and frequency pruning, via stm::textProcessor() (no stemming — Chinese doesn’t inflect the way English does — keeping only tokens of two characters or more) and then stm::prepDocuments(lower.thresh = 2), which drops any term appearing in two or fewer documents across the whole corpus (almost entirely OCR noise and one-off hapax legomena) and, as a consequence, the 41 documents that had nothing left once those terms were gone.

What comes out the other end: 59,106 documents, 144,016 distinct terms, and 3,835,090 tokens actually entered the model — down from 839,579 raw terms before pruning. That pruning step matters enough to state plainly: roughly 83% of the raw vocabulary was noise by this definition, confirming that newspaper OCR text needs aggressive frequency-based cleaning before a topic model can find anything stable in it.

Choosing how many topics

Topic count (K) is not something STM discovers on its own — you have to tell it, and then judge whether you told it the right thing. I ran stm::searchK() across K = 5 through 10 and looked at four diagnostics side by side. Three of them — held-out likelihood, residual dispersion, and the model’s lower bound — move in the same, largely uninformative direction as K grows: a model with more topics will almost always fit the data a little better, training and held-out alike, so on their own these three diagnostics argue for the largest K available without saying anything about whether the topics are actually good. The one diagnostic that behaves differently, and is therefore the one worth trusting, is semantic coherence — how reliably a topic’s top words actually co-occur within the documents that load on it. That measure is not monotonic: it peaked at K=5 and K=8, dipped at K=6–7, and dropped sharply at K=9 before a partial recovery at K=10 that still fell short of the K=8 peak.

On that basis I first narrowed the field to two candidates, K=6 and K=8, and fit both in full. Plotting semantic coherence against a second quality measure, exclusivity — how distinctly a topic’s words belong to it rather than being shared across several topics — settled the question: the eight-topic model dominates the six-topic model on both axes at once, with better coherence and better exclusivity. That is not a subtle trade-off requiring a judgment call; K=6’s topics measurably share more vocabulary with each other than K=8’s do, which is exactly what you’d expect if K=6 is still merging content that K=8 has enough resolution to tell apart. Reading the actual topic word lists confirmed this directly: two of K=8’s topics that looked, at a glance, like a redundant near-duplicate pair (代表/辦法/辦理 vs. 辦法/規定/代表 by their top three words) turned out, once I read their full FREX and Score word lists rather than just the three most frequent words, to be genuinely different — one is warlord-era provincial/military wire news, the other is municipal-governance and labor-affairs news. The apparent overlap was two administrative registers sharing a handful of bureaucratic verbs, not one topic accidentally split in two.

I also ran a robustness check before committing to this decision: since STM’s per-document topic estimate can be noisy for very short documents, I refit K=8 on a version of the corpus filtered to documents of 50 tokens or more (dropping about 19% of the corpus) and compared it against the full, unfiltered fit. Filtering produced a modest coherence improvement but no meaningful exclusivity gain, and — more importantly — it collapsed two topics that the full-corpus model keeps distinct: an older, Qing-register judicial vocabulary (magistrates, canings, the cangue) and the more modern, semi-colonial constabulary register that eventually supersedes it. That distinction is itself part of the story I want to tell in the final section, so throwing it away for a marginal coherence gain was the wrong trade. The full, unfiltered corpus and the eight-topic model (TM8) are what everything from here on is built on.

The data and the tools

Two files carry the actual analytical weight. shopTM (as shopTM.csv) is the cleaned, tokenized text that the model was fit on — 59,210 rows before the final pruning step above removes the 104 documents that don’t survive it. topicprop8.csv is the model’s real output: one row per document, one column per topic, each cell a proportion between 0 and 1, every row summing to 1. This is the document-topic matrix, theta in STM’s own notation, and it is the thing every visualization and every close-reading decision in this post traces back to.

Beyond the model-fitting itself, I used three tools to get from that matrix to something legible. stm’s own diagnostic and summary functions (labelTopics(), plot.STM(), estimateEffect(), findThoughts()) produced the topic word lists and let me pull the specific highest-loading documents for a given topic. LDAvis gave me an interactive, browser-based way to explore each topic’s vocabulary and its relevance-weighted terms — with one caveat worth flagging for anyone who works with these tools: LDAvis re-sorts topics by their share of the corpus’s raw token count for its own display, which does not match the topic numbering used everywhere else (the CSVs, the labels file, stm’s own output), so a screenshot’s “Topic 1” is not reliably the same thing as Topic 1 in the data. stminsights, an R Shiny app, was where I did the actual label-validation pass — reading full word lists topic by topic against the underlying documents to check that the label I wanted to assign a topic actually matched what was in it. All three tools are windows onto the same underlying theta matrix and beta (topic-word) matrix; none of them replace close reading, which is where the final section of this post begins.

What the model shows

Everything in this section comes out of the two files described above — topicprop8.csv and the underlying model fit — filtered down, from the dozen-plus diagnostic plots I generated while doing this analysis, to the four that carry real argumentative weight for a reader who wasn’t in the room for the model-selection process. I want to flag before showing any of them: a chart is the visible tip of a much larger statistical apparatus, and it’s worth resisting the temptation to read more precision into any single bar or line than the underlying estimation actually supports. What follows is what these four outputs contribute, and no more.

Figure 1. Mean 8-topic shares across all 59,210 documents.

The first and simplest question a topic model can answer is: what, in aggregate, is this corpus about? Averaged across all 59,210 documents, one topic — Crime & Police Blotter — accounts for 33.5% of the average document’s topic weight, more than the next two topics combined. Its closest sibling, Police-Referred Civil & Criminal Cases (17.4%), is really the same underlying phenomenon read through a different institutional lens (more on that distinction below). Together, the two crime/court topics make up just over half of everything the model finds in this corpus. This is not a modeling artifact — no reasonable choice of K makes it go away, it only ever gets re-partitioned into finer pieces — and it is the single most important fact about this source base: shopkeepers enter the Shenbao‘s pages overwhelmingly through the police blotter and the courtroom, not through commercial reporting, civic life, or anything else. Three further topics (Political & Administrative Affairs, Municipal Governance & Labor Affairs, and China & Society) form a mid-tier of 7–11% each, and the remaining three — the two advertising genres and general public notices — round out the corpus at 5–8% apiece.

Figure 2. 8-topic shares by year, 1872–1949 (topic_proportion_per_year8.csv).

Averages flatten seventy-seven years into one number, which is why the more historically interesting output is this same set of topic shares plotted year by year. Two things stand out. First, the crime/court supertopic’s dominance is not constant: combining Crime & Police Blotter and Police-Referred Civil & Criminal Cases, it runs at roughly 60–65% of the average document’s weight through the 1870s and 1880s (after two erratic opening years, 1872–73, that are almost certainly a small-sample edge effect — the corpus is thin at the very start), and by the late 1940s has receded to roughly a third — still the largest single presence, but no longer overwhelming everything else. Second, that recession isn’t simply “things get more diverse over time” in some generic sense; specific topics rise to fill the space in a way that tracks real institutional history. Political & Administrative Affairs and Municipal Governance & Labor Affairs are present from the corpus’s earliest years — provincial and local government coverage didn’t need to be invented — but they roughly double their combined share across the Republican decades, from about 12% of the average document around 1872 to 25–30% by the 1930s, as that coverage thickens. Classified Ads stays a minor genre (2–4%) until the 1930s, then rises sharply — 6% by 1930, over 14% by 1940 — and stays elevated through the war years, plausibly tracking the same advertising infrastructure that made “lost and found” and “contact us” notices viable at scale. None of this is news to a historian of the period in the abstract, but seeing it fall directly out of an unsupervised statistical model, with no historical categories fed in ahead of time, is a genuinely useful independent check that the model is tracking something real rather than an artifact of its own construction.

Figure 3. Semantic coherence vs. exclusivity, models K=6/7/8/10 (mean and median).

This is the chart that did the actual work of choosing K=8 over the alternatives, described in the previous section — included here because a reader should be able to see the evidence rather than take the choice on faith. Four candidate models (K=6, 7, 8, 10) are plotted by semantic coherence (x-axis) against exclusivity (y-axis), both as means and medians. K=8 sits furthest right and nearly as high as K=10 on the y-axis — better coherence than every alternative, and exclusivity beaten only by K=10, which pays for that single-axis edge with markedly worse coherence. No other candidate model dominates on both axes simultaneously the way K=8 does.

Table 1. 8 topics ranked by mean document-topic share.

TopicLabelMean share
7Crime & Police Blotter (Local/Mixed-Court Register)33.5%
2Police-Referred Civil & Criminal Cases (French Concession Court)17.4%
4Political & Administrative Affairs (Provincial Government & Warlord-Era News)11.4%
6Municipal Governance & Labor Affairs10.2%
1Medical & Pharmaceutical Advertising8.0%
8Company & Public Notices (Business Transfers, Insurance, Banking)7.7%
5China & Society: Everyday Life, Literature & Art7.0%
3Classified Ads: Lost & Contact Notices5.0%

Figure 4. Topic co-occurrence network (“huge” method).

Finally, a genuinely useful side-effect of fitting a topic model on real prose is that it tells you which topics tend to travel together within the same document — not because they’re the same topic, but because articles that touch one often touch the other. Running stm::topicCorr() in its regularized (“huge”) mode on the model’s document-topic matrix surfaces exactly four positive associations among the twenty-eight possible topic pairs. One is unremarkable — Classified Ads correlates with Company & Public Notices, two notice-board genres that share a page — and one is mixed, Classified Ads with China & Society. The other two are the substantively interesting ones, and both involve topics central to this post: Political & Administrative Affairs correlates with Municipal Governance & Labor Affairs, and China & Society correlates with Municipal Governance & Labor Affairs as well. The first is a nice quantitative confirmation of something already visible in the topic labels — these are two halves of what looked, at K=6, like a single “organizational affairs” topic, still co-occurring in the same articles even after the finer model tells them apart. The second suggests municipal-governance reporting shared column space with broader social and political commentary more often than it shared space with the courts or the classifieds — a plausible pairing for civic-affairs journalism. Everywhere else in the correlation structure, topics are mildly negatively associated or uncorrelated, which is the expected pattern when topics are competing for a fixed budget of words in any given article — an article that’s mostly about a court case has, definitionally, less room left over to also be about a chamber-of-commerce meeting.

Shopkeepers in the dock, and elsewhere

The question I asked at the start of this project was how the Shenbao’s shopkeepers appeared to their contemporaries: as economic actors, as civic leaders, as troublemakers, or as victims. The topic model’s single clearest finding is that this is not a question with one answer, and that the balance between these four roles shifted substantially over seventy-seven years. What follows draws on documents the model itself flagged as strongly representative of one of its five non-advertising topics, then filtered hard by close reading. I set aside the two dedicated advertising/classifieds topics and the general public-notices topic entirely — real genres in their own right, but not where a shopkeeper’s life as a story actually happens — and read roughly 250 of the remaining high-loading candidates, about 50 per topic. Most did not survive: a large share had no real shopkeeper or commercial angle at all despite loading strongly on a topic that, in aggregate, is about commerce and administration, and plenty more were too fragmentary — a bare notice, a wire dispatch, a classified-ad compilation — to serve as a story. Fewer than one in ten held up as both a genuine match and a legible narrative. What survives that filter, below, is not a random sample; it’s a deliberately curated set of documents chosen because they are legible, concrete, and load strongly on their topic. Read them as illustrations of a pattern the aggregate data establishes, not as a representative sample in their own right — and read the rejection rate itself as a finding: even a well-fitting topic model is, at best, a compass for close reading, not a substitute for it.

Victims, again and again

The plainest way shopkeepers enter these pages is as people something happens to. Fire is the recurring disaster: in 1878, a lodging house fire in the French Concession spread to a candle shop, a noodle house, and a congee shop before British and French brigades brought it under control — caused, in the end, by a shop hand testing a newly bought oil lamp. Seventeen years later, in Zhenjiang, a fire that started in a stationer’s shop tore through an entire commercial street, taking with it an inn, a rice shop, a woodware dealer, a barbershop, dye works, tailor shops, and an apothecary whose stock of ginseng and deer-antler medicine burned to nothing. These are not isolated incidents; they are what a dense, wooden, lamp-lit commercial district looked like when something went wrong, and the shops named in these articles read almost like a street directory frozen mid-catastrophe.

Where fire is accidental, later decades bring deliberate predation. In 1923 a gang confessed to a string of armed robberies — a pawnshop, a rice shop, two tobacco dealers — firing pistols and slashing a victim’s arm in the process. By 1947, in the last chaotic years of Nationalist rule, the threat had become political as well as criminal: a Nanshi rice-shop owner, already defrauded of a large wheat payment by an absconding broker, received a forged extortion letter purporting to be signed by Zhu De and Mao Zedong, demanding cash and rice under threat. He reported it to the police rather than pay — but the fact that a shopkeeper’s first assumption, on receiving an anonymous demand, was that it might genuinely be the Communist leadership, says something about how thin the membrane between ordinary commercial risk and the wider civil war had become by then.

The mechanics of credit and the courts

A second, less dramatic but more revealing cluster of documents shows shopkeepers as economic actors navigating a credit economy that ran, in the end, on personal trust and legal recourse in roughly equal measure. In 1884, a money-changer’s shop in Wenzhou owed several hundred dollars to a grocery store; when the grocer came to collect, the debtor blocked his own counter with sacks of sugar, a brawl broke out, opportunists pretended to mediate while pilfering goods amid the chaos, and the money-changer’s business collapsed into bankruptcy soon after. Two years later, in Shanghai’s British Settlement, a silk-thread shop’s clerks tracked down a fraudulent warehouse owner who had renamed his firm and fled in the night, and delivered him themselves to the French police — merchants doing the investigative legwork the concession court system would then formalize. In 1937, in a case that captures just how embedded shopkeepers were in the city’s institutional credit relationships, a dozen named shops — an apothecary, a rice dealer, a lacquerware maker, an ironmonger, two tofu sellers among them — jointly sued the abbot of the Longhua Temple over years of unpaid debts, after the temple’s usual income from its annual incense fair had failed to cover its accounts. Not every collision between commerce and modernity was so fraught: in 1904 a dye shop was hauled before the Mixed Court simply for its habit of drying wet laundry on the Telegraph Company’s wires outside its front door, disrupting transmissions until a magistrate ordered it to stop — a small, almost comic reminder that “modern” Shanghai and older commercial habits were still working out their boundaries block by block.

Troublemakers

The court cases that dominate this corpus are not only about shopkeepers as plaintiffs or victims — plenty appear as defendants, and the register in which they’re punished changes visibly across the period, which is exactly the distinction the topic model itself surfaces as two separate topics rather than one (see the previous section). In 1889, a barber and a carpenter drinking together in a tavern near the county yamen fought over an unpaid bill; the county magistrate personally sentenced the offender to caning and the cangue, paraded publicly at the yamen gate. That is Qing justice in its traditional form — corporal, public, magistrate-administered. By 1917, a teahouse owner caught running an illegal gambling operation was fined by the fully modernized Mixed Court’s joint Sino-foreign bench instead, his proceeds confiscated rather than his back beaten. Between those two poles sits a subtler kind of trouble: in 1875, a furniture-shop tenant sued for unpaid rent could offer the court nothing better than the plea that “business has been quiet, hard to raise the money right now” — a shopkeeper’s excuse that reads, a century and a half later, as entirely familiar.

Not every document in this corpus is about crime, commerce, or civic life at all — some are simply about the people behind the counter. In 1929, an aging craftsman at a Shanghai leather-suitcase shop, overcome by an irreconcilable quarrel with his wife, wrote a suicide note, sent it back to the shop by a teahouse boy, and drowned himself in the Huangpu. It is the only document in this set with no institutional angle whatsoever — no court, no bureau, no guild — and it is a useful reminder that “shopkeeper” in this corpus also meant an employee with a private life the newspaper only glimpsed in passing, on its way to a different story.

Civic actors

The fourth register — shopkeepers as an organized political constituency rather than individuals — appears earlier than the aggregate chronology might suggest, and it’s the strand that grows most steadily through the Republican decades represented in the topic-over-time chart above. As early as 1877, when the Zhejiang provincial governor ordered awnings and sheds torn down near the yamen gate as a fire hazard, silk-and-satin shop owners organized a petition — through local gentry-merchant intermediaries — arguing the awnings protected goods from sun and rain, and won an exemption. In 1916, soldiers searching for illegally stored salt raided a wine shop at dawn, terrifying the neighborhood; when troops later marched through firing shots near other merchants, the entire commercial district closed its doors in a coordinated strike (罷市), and local merchant leaders reported the incident directly to the county magistrate. By the war years, that same civic infrastructure was doing quieter, more bureaucratic work: in 1939, hoteliers in the Japanese-occupied district organized to demand jurisdictional transfer to the British-run International Settlement, amid worries over food, milk, and coal supply — merchants as a lobbying bloc navigating occupation-era administration, not just its victims.

What this adds up to

None of these fifteen documents is statistically representative of anything on its own — that is not what close reading is for. What they do, together, is put flesh on a pattern the aggregate numbers can only gesture at: that “shopkeeper,” as a category the Shenbao‘s readers would have recognized, moved between victim, defendant, creditor, and civic actor within the same decade, sometimes within the same article. The topic model didn’t write this narrative — it did what I said at the outset it could do: it narrowed 59,210 documents down to a tractable set of candidates, told me roughly where to look, and got the balance of genres in the corpus right at an aggregate level. Reading the actual articles was still the only way to find out whether any given candidate was a real example or a false positive — and, this time, well over nine in ten of them were the latter. That rejection rate is itself worth remembering the next time a topic proportion looks like an answer rather than a lead.

Christian Henriot
Christian Henriot

OpenEdition suggests that you cite this post as follows:
Christian Henriot (September 7, 2026). Behind the Counter: Topic Modelling — A Compass, Not a Substitute. Blog Virtual Shanghai. Retrieved October 6, 2026 from https://doi.org/10.58079/16qfu


You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.