Description
rwhatsapp is a straightforward, robust R package for importing and parsing exported WhatsApp chat logs (Android/iOS) into tidy tabular data. It ingests .txt and .zip history files across locales/devices and exposes message text, timestamps, authors, and emojis for downstream analysis.
Use Cases
- Import exported WhatsApp chats to study interpersonal communication
- Describe conversations (e.g., messages per day; messages per author) to study activity and participation.
- Explore emoji usage patterns and look up emoji names to understand affective dynamics.
- Conduct token-based analyses (e.g., most-used words, tf–idf per author) with standard text-mining workflows.
- Teaching: demonstrate tidy text pipelines on personal communication data.
Input Data
- Accepted inputs: WhatsApp chat exports in plain text (
.txt) or compressed archives (.zip) created via the app’s export function. - Locales/devices: Designed to handle multiple locales and both Android/iOS.
- Example files that come with the package: sample.txt[
system.file("extdata", "sample.txt", package = "rwhatsapp")]
Typical Structure
Lines with timestamps, author handles, message text; media as placeholders. If you extract it and open the .txt file it should look like this:
[06/03/25, 2:27:42] Markus: I just need a quick coffee, and then I’ll be back to normal. Hahaha [06/03/25, 2:27:47] Angela: My day has been totally random, but I’ll be right back as well!
Output Data
rwa_read() returns a tibble: - time, author, text, source, emoji, emoji_name
library("rwhatsapp")
history <- system.file("extdata", "sample.txt", package = "rwhatsapp")
chat <- rwa_read(history)
head(chat)
# A tibble: 6 × 6
time author text source emoji emoji_name
<dttm> <fct> <chr> <chr> <list> <list>
1 2017-07-12 22:35:00 <NA> "Messages to thi… /srv/… <NULL> <NULL>
2 2017-07-12 22:35:00 <NA> "You created gro… /srv/… <NULL> <NULL>
3 2017-07-12 22:35:00 Johannes Gruber "<Media omitted>" /srv/… <NULL> <NULL>
4 2017-07-12 22:35:00 Johannes Gruber "Fruit bread wit… /srv/… <chr> <chr [2]>
5 2017-07-13 09:12:00 Test "It's fun doing … /srv/… <NULL> <NULL>
6 2017-07-13 09:16:00 Johannes Gruber "Haha it sure is… /srv/… <chr> <chr [1]>
Hardware Requirements
- R: ≥ 3.5.0
- Resources: Small-to-moderate for typical chats.
Environment Setup
With R installed run:
install.packages("rwhatsapp")
library("rwhatsapp")
OR
remotes::install_github("JBGruber/rwhatsapp")
library("rwhatsapp")
Loading Dependencies:
RWhatsApp needs a number of other packages to be installed to ensure functionality. Always make sure to load these common packages into your environment when using RWhatsapp:
library("dplyr")
library("ggplot2")
library("lubridate")
library("tidyr")
library("tidytext")
library("stopwords")
library("magick")
library("ggimage")
How to Use
In the following example we will show you how to use the main features of the package. You may use the example data or are welcome to load your own chatlogs into the environment. In order to upload your chatlogs, you can use the “Upload File”-Function of R-Studio in this environment.
Load sample data and read into R
chat <- rwa_read("ExampleChat.txt")
chat
# A tibble: 4,547 × 6
time author text source emoji emoji_name
<dttm> <fct> <chr> <chr> <list> <list>
1 2025-06-02 14:13:50 JSE Esports "Messages and calls… Examp… <NULL> <NULL>
2 2025-06-02 14:13:50 JSE Esports "You created the gr… Examp… <NULL> <NULL>
3 2025-06-02 14:13:54 Markus "Morning everyone" Examp… <NULL> <NULL>
4 2025-06-02 14:14:17 Markus "Today it would be … Examp… <NULL> <NULL>
5 2025-06-02 14:14:29 Angela "hii" Examp… <NULL> <NULL>
6 2025-06-02 14:14:32 Angela "I'll be at my PC f… Examp… <NULL> <NULL>
7 2025-06-02 14:14:39 Julian "hey" Examp… <NULL> <NULL>
8 2025-06-02 14:15:01 Markus "I'll be there from… Examp… <NULL> <NULL>
9 2025-06-02 14:15:09 Julian "that is cursed" Examp… <NULL> <NULL>
10 2025-06-02 14:15:22 Angela "I feel personally … Examp… <NULL> <NULL>
# ℹ 4,537 more rows
Loading own data
chat <- rwa_read("/path/to/your/WhatsAppChat.txt")
Remove system messages
In this step we are removing any messages, that are not sent from one of the two human authors in the chat. You may have seen an example of this in the Output-Data-Chapter earlier.
chat <- subset(chat, !is.na(author))
Messages per day
We are now able to extract i.E. how many messages were sent per day or on a specific day by both authors:
theme_set(theme_minimal())
chat %>%
mutate(day = date(time)) %>%
count(day) %>%
ggplot(aes(day, n)) +
geom_col() +
labs(
title = "Messages per Day",
x = "Date",
y = "Number of Messages"
) +
scale_x_date(date_labels = "%d.%m.%Y")
Emoji exploration
Sometimes it is of interest, which and how often emojis are used in a given chat. By using the following code chunk we can examine this further:
chat %>%
unnest(emoji) %>%
count(author, emoji, sort = TRUE) %>%
rename(
Author = author,
Emoji = emoji,
Frequency = n
) %>%
knitr::kable()
| Author | Emoji | Frequency |
|---|---|---|
| Max | 👍 | 23 |
| Jules | 👍 | 11 |
| Angela | 😭 | 6 |
| Richard | 👍 | 5 |
| Casper | 👍 | 3 |
| Jason | 👍 | 3 |
| Jerry | 👍 | 3 |
| Tjark | 👍 | 3 |
| Michael | 👍 | 2 |
| Felix | 👍 | 1 |
Token-based exploration
We may also try to see how often a given author used a specific word/wording. By using the following code chunk we can examine this further:
chat %>%
tidytext::unnest_tokens(input = text, output = word) %>%
count(author, word, sort = TRUE) %>%
rename(
Author = author,
Word = word,
Frequency = n
) %>%
select(Author, Word, Frequency)
# A tibble: 1,969 × 3
Author Word Frequency
<fct> <chr> <int>
1 Markus the 507
2 Markus a 371
3 Markus then 354
4 Markus i'm 334
5 Max omitted 304
6 Max sticker 269
7 Markus be 259
8 Markus and 253
9 Markus for 248
10 Markus to 240
# ℹ 1,959 more rows
This is not very useful at this point, because the analysis is “polluted” with words like “the”, “a” or “omitted”. How to remove those words in order to make the analysis more fruitful will be shown in the next chapter.
Deep Dive
After you are familiar with the package and its basic functionalities you are able to combine the diverse feature together to undergo deeper analysis. The following example will work especially well, if you have loaded your own WhatsApp-Data:
Another way to determine favourite words is to calculate the term frequency–inverse document frequency (tf–idf). Basically, what the measure does, in this case, is to find words that are common within the messages of one author but uncommon in the rest of the messages.
# First we define stopwords to be removed from the analysis. You may need to add further words to this list while investigating the dataset, such as "omitted". "Omitted" is a placeholder WhatsApp puts into the log file instead of a picture or video. Try to run the chunk and then add more words to the list to be removed, in order to make the analysis more fruitful.
to_remove <- c(stopwords(language = "en"),
"addmorewordstoberemovedhere")
# Then we load our own dataframe (or leave it as is to use our larger example dataset)
chat <- rwa_read("ExampleChat.txt")
#Then we remove all system messages from the dataset
chat <- subset(chat, !is.na(author))
chat %>%
unnest_tokens(input = text, output = word) %>%
select(word, author) %>%
filter(!word %in% to_remove) %>%
mutate(word = gsub(".com", "", word)) %>%
mutate(word = gsub("^gag", "9gag", word)) %>%
count(author, word, sort = TRUE) %>%
bind_tf_idf(term = word, document = author, n = n) %>%
filter(n > 10) %>%
group_by(author) %>%
slice_max(tf_idf, n = 6, with_ties = FALSE) %>%
ggplot(aes(x = reorder_within(word, tf_idf, author),
y = tf_idf,
fill = author)) +
geom_col(show.legend = FALSE) +
geom_text(aes(label = n), hjust = -0.2, size = 3) +
ylab("") +
xlab("") +
coord_flip() +
facet_wrap(~author, ncol = 2, scales = "free_y") +
scale_x_reordered() +
ggtitle("Frequency of each author's most distinctive words (selected by tf–idf)")
For further deep dives and more in depth tutorials visit the official documentation page.
Technical Details
See the CRAN REPOSITORY for technical information.
References
- Gruber, J. (2022). rwhatsapp: Import and handling for “WhatsApp” chat logs (Version 0.2.4). CRAN. https://doi.org/10.32614/CRAN.package.rwhatsapp
Disclaimer
This method is intended for academic research; ensure legality and ethics when processing chat data.
Contact Details
- Issues: https://github.com/JBGruber/rwhatsapp/issues
- Contact: Johannes Gruber JohannesB.Gruber@gmail.com