Milestone Report
Introduction
The objective of this report is to perform an exploratory analysis of
the three English text datasets provided for the Data Science Capstone
project: blogs, news and Twitter.
The final goal of the project is to build a predictive text algorithm
capable of suggesting the next word in a sentence and to implement it in
a Shiny application.
library(stringi)
library(ggplot2)
library(dplyr)
Loading the data
The three English datasets are loaded from the downloaded corpus.
blogs_file <- "C:/Users/jjesu/OneDrive/Documentos/final/en_US/en_US.blogs.txt"
news_file <- "C:/Users/jjesu/OneDrive/Documentos/final/en_US/en_US.news.txt"
twitter_file <- "C:/Users/jjesu/OneDrive/Documentos/final/en_US/en_US.twitter.txt"
blogs <- readLines(blogs_file, encoding = "UTF-8", skipNul = TRUE)
news <- readLines(news_file, encoding = "UTF-8", skipNul = TRUE)
## Warning in readLines(news_file, encoding = "UTF-8", skipNul = TRUE): incomplete
## final line found on
## 'C:/Users/jjesu/OneDrive/Documentos/final/en_US/en_US.news.txt'
twitter <- readLines(twitter_file, encoding = "UTF-8", skipNul = TRUE)
Basic summary
First, the size, number of lines and approximate number of words in
each dataset are calculated.
file_sizes <- c(
file.info(blogs_file)$size / 1024^2,
file.info(news_file)$size / 1024^2,
file.info(twitter_file)$size / 1024^2
)
line_counts <- c(
length(blogs),
length(news),
length(twitter)
)
word_counts <- c(
sum(stri_count_words(blogs)),
sum(stri_count_words(news)),
sum(stri_count_words(twitter))
)
summary_data <- data.frame(
Dataset = c("Blogs", "News", "Twitter"),
Size_MB = round(file_sizes, 2),
Lines = line_counts,
Words = word_counts
)
summary_data
## Dataset Size_MB Lines Words
## 1 Blogs 200.42 899288 37546806
## 2 News 196.28 77259 2674561
## 3 Twitter 159.36 2360148 30096690
The datasets contain a large amount of text from different sources.
Twitter contains a particularly large number of individual text entries,
while blog entries tend to be considerably longer.
Text length
The length of each line was calculated in characters to better
understand the structure of the three datasets.
blog_length <- nchar(blogs)
news_length <- nchar(news)
twitter_length <- nchar(twitter)
length_summary <- data.frame(
Dataset = c("Blogs", "News", "Twitter"),
Mean = round(c(
mean(blog_length),
mean(news_length),
mean(twitter_length)
), 2),
Median = c(
median(blog_length),
median(news_length),
median(twitter_length)
),
Maximum = c(
max(blog_length),
max(news_length),
max(twitter_length)
)
)
length_summary
## Dataset Mean Median Maximum
## 1 Blogs 229.99 156 40833
## 2 News 202.43 186 5760
## 3 Twitter 68.68 64 140
This analysis shows clear differences between the sources. Tweets are
generally short because of the nature of the platform, while blog and
news entries can contain much longer pieces of text.
Distribution of text length
Because the complete datasets are very large, a random sample of
10,000 observations from each dataset is used for visualization.
set.seed(123)
blogs_sample <- sample(blogs, min(10000, length(blogs)))
news_sample <- sample(news, min(10000, length(news)))
twitter_sample <- sample(twitter, min(10000, length(twitter)))
sample_data <- data.frame(
text = c(
blogs_sample,
news_sample,
twitter_sample
),
Dataset = c(
rep("Blogs", length(blogs_sample)),
rep("News", length(news_sample)),
rep("Twitter", length(twitter_sample))
)
)
sample_data$characters <- nchar(sample_data$text)
ggplot(sample_data, aes(x = characters)) +
geom_histogram(bins = 50) +
facet_wrap(~Dataset, scales = "free_y") +
coord_cartesian(xlim = c(0,1000)) +
labs(
title = "Distribution of text length",
x = "Number of characters",
y = "Frequency"
) +
theme_minimal()

The histogram illustrates that Twitter messages are concentrated at
shorter text lengths, whereas blogs and news contain a wider
distribution of text lengths.
Word frequency
A basic word-frequency analysis was also performed using the random
sample.
all_sample <- paste(
blogs_sample,
news_sample,
twitter_sample,
collapse = " "
)
words <- unlist(
strsplit(
tolower(all_sample),
"\\s+"
)
)
words <- gsub(
"[^a-z']",
"",
words
)
words <- words[words != ""]
word_table <- sort(
table(words),
decreasing = TRUE
)
head(word_table, 20)
## words
## the to and a of in i that for is it on with
## 43987 24248 23089 21164 18750 14806 13256 9521 9233 8996 7777 6896 6531
## you was at this be my as
## 6423 5870 4881 4732 4717 4644 4610
The most frequent words can also be represented graphically.
top_words <- data.frame(
word = names(word_table[1:20]),
frequency = as.numeric(word_table[1:20])
)
ggplot(
top_words,
aes(
x = reorder(word, frequency),
y = frequency
)
) +
geom_col() +
coord_flip() +
labs(
title = "20 most frequent words",
x = "Word",
y = "Frequency"
) +
theme_minimal()

Main findings
The exploratory analysis reveals several important characteristics of
the corpus.
The Twitter dataset contains a very large number of short text
entries. In contrast, blogs contain longer pieces of text and show much
greater variation in text length. News articles also contain relatively
long and structured text.
The frequency analysis shows that common English words dominate the
corpus. Before developing the prediction model, additional text cleaning
will therefore be required.
Another important aspect is the large size of the datasets.
Processing the complete corpus for every operation would require
considerable memory and computational resources. Sampling and efficient
text-processing techniques will therefore be useful during model
development.
Prediction strategy
The next step of the project will consist of preparing the text for
the predictive algorithm.
The text will first be converted to lowercase and unnecessary
punctuation, numbers and special characters will be removed. The cleaned
text will then be tokenized into individual words. After preprocessing,
sequences of words called n-grams will be created.
For example:
- unigram: “data”
- bigram: “data science”
- trigram: “data science project”
The frequencies of these sequences will be calculated from the
corpus. The prediction algorithm will use these frequencies to estimate
the most likely word following a sequence entered by the user. For
example, if the user enters:
“thank you for”
the model will search the n-gram frequency tables and return the most
probable next word. Higher-order n-grams will be used whenever enough
information is available. If a sequence cannot be found, the algorithm
will fall back to shorter n-grams. This approach should provide a
balance between prediction accuracy, computational efficiency and
application speed.
Shiny application
The final prediction algorithm will be implemented in an interactive
Shiny application.
The user will enter a sentence or group of words into a text box. The
application will process the input and use the n-gram prediction model
to determine the most likely next word. The predicted word, or
potentially several candidate words, will then be displayed to the
user.
The application will therefore provide a simple demonstration of
predictive text technology similar to the word prediction systems used
in mobile keyboards.
Conclusion
This exploratory analysis provides an overview of the three English
text datasets used in the Data Science Capstone project.
The datasets contain millions of words from blogs, news articles and
Twitter messages and represent different forms of written
communication.
The analysis of file sizes, number of lines, number of words and text
lengths demonstrates important differences between the three
sources.
These results provide the foundation for the next stage of the
project: cleaning the text, constructing n-gram frequency models and
developing a predictive text algorithm that will ultimately be deployed
through a Shiny application.