Which emoji go against the grain of their text?
Source:R/emoji-incongruity.R
emoji_incongruity_profile.Rdemoji_incongruity_profile() aggregates emoji_incongruity() by glyph: for
each emoji, how far from its host text's sentiment it typically sits, and how
often it appears with the opposite polarity. Those are the candidate irony
markers in your corpus.
Arguments
- data
A data frame or tibble containing a text column. Grouped data frames are accepted. The verbs that work a row at a time (adding columns, or keeping and expanding rows) carry the grouping through to their result, as
dplyr::mutate()anddplyr::filter()do. The verbs that pool across rows – the counts, the co-occurrence edge lists, the time series – warn that they ignore the grouping and return one corpus-wide answer.- text
The text column to scan, supplied unquoted. Any atomic column is accepted and read as character, so a
factorworks and a numeric,Dateor logical one simply contains no emoji. A list column – or a data-frame column – is refused rather than coerced, because coercing one deparses it and the emoji found would be in the code rather than in your data. What counts as an emoji is the same in every verb; see the Detection section of tidyEmoji for the one case that surprises people, code points that are emoji only when they carryU+FE0F.- text_score
Unquoted numeric column holding the text's own sentiment.
- method
"difference"(default) for the continuous gap, or"sign_flip"for the categorical polarity-flip feature.- scale
How to make the two scores comparable:
"rank","zscore"or"none". Required – there is no sensible default."rank"and"zscore"are computed over the rows carrying both an emoji score and atext_score, not over the whole corpus, so rows with no scorable emoji cannot shift the answer for the rows that have one.- where
"all"(default) scores every emoji in the row;"final"scores only the trailing run of emoji that ends the text.- threshold
For
method = "difference", the absolute gap at or above which.emoji_incongruentisTRUE. Default1, a full polarity swing on the rank scale."sign_flip"has no gap to cut, so supplying both warns rather than letting half the call do nothing silently. A threshold at or below0flags every scored row,abs(gap)never being negative.- min_n
Minimum number of scored occurrences for an emoji to be reported. Default
5.
Value
A tibble with one row per emoji: emoji, name, n (scored
occurrences), mean_incongruity, sd_incongruity, n_flips and
flip_rate, sorted by descending flip_rate, then descending n,
then the glyph, so the order is fully determined. The first key ties
readily: every glyph that never flips scores 0, and one that always
does scores 1.
Details
Incongruity is a property of a row, so every emoji in a row is credited with
that row's gap. A glyph that habitually shares a message with a genuinely
incongruent one will therefore inherit some of its score; read n alongside
flip_rate before drawing conclusions from a handful of occurrences.
Glyphs are canonicalised through the package's codepoint key, so two spellings of one emoji make one row rather than two; see Which spelling comes back in tidyEmoji.
Examples
df <- data.frame(
text = c("great \U0001f621", "lovely \U0001f621", "awful \U0001f621"),
score = c(0.8, 0.7, -0.9)
)
emoji_incongruity_profile(df, text, score, scale = "none", min_n = 1)
#> # A tibble: 1 × 7
#> emoji name n mean_incongruity sd_incongruity n_flips flip_rate
#> <chr> <chr> <int> <dbl> <dbl> <int> <dbl>
#> 1 😡 enraged face 3 -0.373 0.954 2 0.667