Which emoji are used together is a network question, and
emoji_pairs() returns exactly the edge list a network
package wants. The trap is that the edge list it returns by default is
mostly noise, and a layout draws noise as confidently as it draws
structure. This article builds an emoji network that is worth drawing:
weighted by an association measure, thresholded on frequency, and
checked against what the emoji-network literature says such networks
look like.
library(tidyEmoji)
library(dplyr)
posts <- read.csv(system.file("extdata", "ata_tweets.csv",
package = "tidyEmoji"),
stringsAsFactors = FALSE, encoding = "UTF-8")One row per pair of distinct emoji that appear in the same post, with the number of posts in which they do:
edges <- posts %>% emoji_pairs(full_text)
edges
#> # A tibble: 213 Γ 3
#> item1 item2 n
#> <chr> <chr> <int>
#> 1 π π 10
#> 2 π π© 4
#> 3 π π 3
#> 4 π π 3
#> 5 π π₯° 2
#> 6 π π₯Ί 2
#> 7 π― π€·π½ββοΈ 2
#> 8 π π€ 2
#> 9 π π€£ 2
#> 10 π π€·πΌββοΈ 2
#> # βΉ 203 more rows
edges %>% count(n, name = "pairs")
#> # A tibble: 5 Γ 2
#> n pairs
#> <int> <int>
#> 1 1 200
#> 2 2 9
#> 3 3 2
#> 4 4 1
#> 5 10 1200 of the 213 edges (93.9%) are a single post. A graph drawn from all of them is one postβs worth of evidence per line, and the few heavy edges belong to the emoji that are common everywhere, which pair with everything because they are common, not because they are related.
Two changes fix this, and they do different jobs.
measure = "dice" is
2 * n / (n1 + n2), with n1 and n2
the posts holding each emoji: 1 for a pair never seen apart, near 0 for
a pair that is mostly apart. "ppmi" and
"log_odds" are the alternatives; see
?emoji_pairs.weighted <- posts %>%
emoji_pairs(full_text, measure = "dice") %>%
filter(n >= 2)
weighted
#> # A tibble: 13 Γ 4
#> item1 item2 n dice
#> <chr> <chr> <int> <dbl>
#> 1 π π₯Ί 2 0.222
#> 2 π π₯° 2 0.182
#> 3 π― π€·π½ββοΈ 2 0.182
#> 4 π π 10 0.121
#> 5 π π 3 0.0659
#> 6 π π© 4 0.064
#> 7 π π 3 0.0526
#> 8 π π₯° 2 0.0460
#> 9 π π₯΄ 2 0.0440
#> 10 π π€·πΌββοΈ 2 0.0417
#> 11 π π€ 2 0.0396
#> 12 π π₯° 2 0.0364
#> 13 π π€£ 2 0.0339That is the honest network for this corpus: 13 edges. Two thousand
posts holding 900 emoji are too few for a network of more than a handful
of emoji, and it is better to know that than to draw the 213-edge
version. A corpus of hundreds of thousands of posts, or one pooled by
user or by conversation with doc_id, gives a graph with
real structure.
The edge list feeds igraph (or tidygraph)
directly, with the association measure as the edge weight:
g <- igraph::graph_from_data_frame(
weighted[, c("item1", "item2", "dice", "n")], directed = FALSE)
igraph::vcount(g)
#> [1] 14
igraph::ecount(g)
#> [1] 13
igraph::components(g)$no
#> [1] 3Community detection then groups emoji that are used together more than chance; Louvain with the Dice weight is a reasonable default:
set.seed(2026) # Louvain breaks ties at random; fix them for a stable answer
communities <- igraph::cluster_louvain(g, weights = igraph::E(g)$dice)
split(igraph::V(g)$name, igraph::membership(communities))
#> $`1`
#> [1] "π" "π₯Ί"
#>
#> $`2`
#> [1] "π" "π₯°"
#>
#> $`3`
#> [1] "π―" "π€·π½ββοΈ"
#>
#> $`4`
#> [1] "π" "π" "π" "π©" "π₯΄" "π€·πΌββοΈ" "π€" "π€£"Drawing it is a job for a graph-plotting package. With
ggraph installed, and ragg as the graphics
device so the glyphs render in colour:
Studies of emoji co-occurrence networks on large Twitter samples (Fede et al., 2018; Alsaif et al., 2021) report two properties, and both make good checks that a network is measuring structure rather than sampling noise:
Both are one line once the graph exists. On a network of a dozen nodes they say little; on a real one, a degree table with no tail or a community count close to the node count is a sign that the threshold was set too low:
emoji_pairs(directed = TRUE) orders each pair by first
appearance in the post, so the edge from one emoji to another counts the
posts where the first came first. The same measures apply to that
ordered event, and emoji_ngrams() gives the strictly
consecutive version for Markov-style models of emoji sequences.
Alsaif H, Roesch P, Othman S (2021). Analyzing Co-occurrence Networks of Emojis on Twitter. In Intelligent Computing, Springer. https://doi.org/10.1007/978-3-030-80126-7_7
Fede H, Herrera I, Mahdi Seyednezhad SM, Menezes R (2018). Representing Emoji Usage Using Directed Networks: A Twitter Case Study. In Complex Networks & Their Applications VI. https://doi.org/10.1007/978-3-319-72150-7_67