Word Clouds

Word Clouds#

Navigation: ← Previous: Term Frequency | Next: Character Presence →

Vocabulary at a glance: one cloud per novel, then beginning / middle / end thirds for three contrasting plots.

Method#

Word clouds are a blunt instrument, but they are a good first look at what remains after English stopwords and Gutenberg artefacts (chapter, gutenberg, said, mr…) are removed. Later thirds of a book should not look like the opening if the plot has moved.

import sys
from pathlib import Path
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objects as go
import plotly.express as px
from IPython.display import HTML, display
import warnings
warnings.filterwarnings('ignore')
plt.style.use('seaborn-v0_8-whitegrid')

PROJ_DIR = Path('.').resolve()
if not (PROJ_DIR / 'gutenberg_utils.py').exists():
    PROJ_DIR = Path('projects/literary-nlp').resolve()
if str(PROJ_DIR) not in sys.path:
    sys.path.insert(0, str(PROJ_DIR))

from gutenberg_utils import (
    load_pages, book_catalog, title_of, BOOK_COLORS, BOOKS,
    THEMATIC_KEYWORDS, all_stopwords, ensure_nltk_data,
    add_vader_sentiment, add_nrc_emotions, NRC_EMOTIONS,
    keyword_counts, character_mentions, third_label,
)

def display_plotly(fig):
    """Embed Plotly with CDN JS — fig.show() is blank in Jupyter Book HTML."""
    display(HTML(fig.to_html(include_plotlyjs='cdn', full_html=False)))

PAGES = load_pages()
CATALOG = book_catalog()
print(f"Loaded {len(PAGES):,} pages across {PAGES['book_id'].nunique()} books")
Loaded 2,653 pages across 8 books
from wordcloud import WordCloud
import matplotlib.font_manager as fm

STOPS = all_stopwords()
FONT = fm.findfont(fm.FontProperties(family='DejaVu Sans'))

def cloud_image(text, width=700, height=420):
    wc = WordCloud(
        width=width, height=height, background_color='white',
        stopwords=STOPS, colormap='copper', max_words=80, collocations=False,
        random_state=1, font_path=FONT,
    )
    return wc.generate(text).to_array()

book_ids = [b['book_id'] for b in BOOKS]
fig, axes = plt.subplots(4, 2, figsize=(12, 16))
for ax, book_id in zip(axes.ravel(), book_ids):
    text = ' '.join(PAGES.loc[PAGES['book_id'] == book_id, 'text'].astype(str))
    ax.imshow(cloud_image(text), interpolation='bilinear')
    ax.set_title(title_of(book_id), color=BOOK_COLORS[book_id])
    ax.axis('off')
plt.tight_layout()
out = PROJ_DIR / 'figures' / '05_wordclouds.png'
fig.savefig(out, dpi=110)
plt.close()
print('Saved', out)
Saved /Users/areeslindley/Documents/Git_repositories/projects-website/projects/literary-nlp/figures/05_wordclouds.png

Whole-book word clouds

Beginning, middle, end#

Three books with different promised arcs: gothic tightening (Dracula), redemption (A Christmas Carol), and social resolution (Pride and Prejudice).

focus = ['dracula', 'christmas_carol', 'pride_and_prejudice']
thirds = PAGES.copy()
thirds['third'] = third_label(thirds['progress'])
fig, axes = plt.subplots(len(focus), 3, figsize=(12, 10))
for i, book_id in enumerate(focus):
    for j, label in enumerate(['beginning', 'middle', 'end']):
        chunk = thirds.loc[(thirds['book_id'] == book_id) & (thirds['third'] == label), 'text']
        axes[i, j].imshow(cloud_image(' '.join(chunk.astype(str)), width=500, height=320),
                          interpolation='bilinear')
        axes[i, j].axis('off')
        bits = []
        if j == 0:
            bits.append(title_of(book_id))
        if i == 0:
            bits.append(label.capitalize())
        if bits:
            axes[i, j].set_title(' — '.join(bits) if len(bits) == 2 else bits[0])
plt.tight_layout()
thirds_path = PROJ_DIR / 'figures' / '05_wordclouds_thirds.png'
fig.savefig(thirds_path, dpi=110)
plt.close()
print('Saved', thirds_path)
Saved /Users/areeslindley/Documents/Git_repositories/projects-website/projects/literary-nlp/figures/05_wordclouds_thirds.png

Beginning, middle, and end word clouds

If the method is working, Carol’s closing third should look more like christmas / blessing / good than counting-house / clerk; Dracula should pick up hunt-and-night vocabulary; Elizabeth and Darcy should still dominate Austen, with marriage more visible late than early.


Navigation: ← Previous: Term Frequency | Next: Character Presence →