
Textstat is a Python library used for calculating statistical measures from text. A useful tool for quantifying text complexity and readability, we introduced textstat and its basic functionality in a previous article. This time around we will move beyond the fundamentals and learn how to calculate and understand text readability scores with the library.
If you have yet to read the previous article, I suggest you start there first.
Readability Scores
First we will see how to get readability scores of text using textstat. Here is a function that will do just that.
import textstat
import pandas as pd
import matplotlib.pyplot as plt
def get_readability_scores(text):
"""Get all major readability metrics at once"""
return {
'flesch_ease': textstat.flesch_reading_ease(text),
'flesch_grade': textstat.flesch_kincaid_grade(text),
'gunning_fog': textstat.gunning_fog(text),
'smog': textstat.smog_index(text),
'ari': textstat.automated_readability_index(text),
'coleman_liau': textstat.coleman_liau_index(text)
}
We will also create a simple function for helping us quickly interpret the Flesch readability score.
def interpret_flesch(score):
"""Interpret Flesch score"""
if score >= 90: return 'Very Easy - 5th grade'
elif score >= 80: return 'Easy - 6th grade'
elif score >= 70: return 'Fairly Easy - 7th grade'
elif score >= 60: return 'Standard - 8th-9th grade'
elif score >= 50: return 'Fairly Difficult - 10th-12th grade'
elif score >= 30: return 'Difficult - College'
else: return 'Very Difficult - College Graduate'
Let’s compare different types of writing:
texts = {
'scientific': """The results demonstrate a statistically significant correlation
between atmospheric carbon dioxide concentrations and global
mean temperature anomalies (p < 0.001).""",
'news': """Local officials announced today that the city's recycling program
will expand next month. Residents will receive new bins next week.""",
'children': """The big red dog ran to the park. He saw a ball and started to
play. His tail wagged happily."""
}
# Calculate scores for all texts
scores_df = pd.DataFrame({name: get_readability_scores(text)
for name, text in texts.items()})
# Add interpretations
scores_df.loc['flesch_interpretation'] = scores_df.loc['flesch_ease'].apply(interpret_flesch)
print(scores_df)
And here is the output.
scientific news children
flesch_ease -15.5 61.33 98.51
flesch_grade 20.1 7.2 1.2
gunning_fog 20.23 10.0 2.68
smog 0.0 0.0 6.4
ari 24.0 10.2 -1.0
coleman_liau 25.47 13.14 0.06
flesch_interpretation Very Difficult - College Graduate Standard - 8th-9th grade Very Easy - 5th grade
Visualizing the Differences
Let's visualize the differences in our results. The following function can help accomplish this.
def plot_readability_comparison(df, metric='flesch_ease'):
df.loc[metric].plot(kind='bar')
plt.title(f'{metric.replace("_", " ").title()} by Text Type')
plt.ylabel('Score')
plt.tight_layout()
plt.show()
And we could call the function like so:
plot_readability_comparison(scores_df)
And our output:

Tracking Readability Changes
Need to track readability over document sections? No problem! Here's how:
def analyze_text_sections(text, section_size=1000):
"""Analyze readability of text in sections"""
# Split text into roughly equal sections
words = text.split()
sections = [' '.join(words[i:i + section_size])
for i in range(0, len(words), section_size)]
# Get scores for each section
section_scores = [get_readability_scores(section)
for section in sections]
return pd.DataFrame(section_scores)
And here is how we could use this function:
# Load and analyze sample text
with open('sample.txt', 'r') as file:
text = file.read()
# Analyze text in sections of 200 words
results = analyze_text_sections(text, section_size=200)
print(results)
And here is a sample result:
flesch_ease flesch_grade gunning_fog smog ari coleman_liau 0 75.71 5.8 9.00 10.4 6.8 8.28 1 -10.73 18.3 21.72 17.5 20.9 24.70 2 -33.43 22.9 26.40 21.0 25.7 27.90 3 -46.63 28.0 30.98 26.2 31.9 27.80
Common Pitfalls
Here are a few common pitfalls associated with finding and interpreting readability scores to keep an eye out for:
- Short texts (<100 words) give unreliable scores
- Technical terms artificially inflate scores
- Different formulas can vary significantly
- Formatting can affect scores
Wrapping Up
And that's all you need for basic readability analysis. You can use these tools to ensure your text matches your target audience. Keep an eye out for more information on how to use textstat for additional statistical analysis tasks in the near future.
