emoji_position() reports, for each row, the character position of the
first and last emoji and the mean relative position of all emoji
occurrences, from 0 (the very start of the text) to 1 (the very end). The
Emoji Sentiment Ranking (Kralj Novak et al., 2015) tracks the same relative
position, and it is a studied signal: emoji cluster near the end of
messages.
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.
Value
data, as a tibble, with added columns .emoji_n, .emoji_first
and .emoji_last (code-point offsets where the first/last emoji start)
and .emoji_rel_position (mean relative position in [0, 1], counting
each emoji as one position). Rows without emoji get NA positions.
Details
.emoji_first and .emoji_last are code-point offsets, the unit
substr() uses, so they can be fed straight back to it.
.emoji_rel_position is not measured in code points. Each emoji counts as
one position however many code points it is built from, so an emoji that is
the last thing in the text scores 1 whether it is a single-code-point
smiley, a two-code-point flag or a seven-code-point family. Counting code
points instead put a sentence-final family emoji a third of the way through
its message. Everything that is not an emoji still counts one position per
code point, so a combining accent elsewhere in the text counts twice; that
affects the denominator only, and only for text carrying such marks.
A text that collapses to a single position cannot tell its start from its
end, and .emoji_rel_position is 0 there by convention. That is exactly
the row whose whole content is one emoji and nothing else, which a chat or
reaction corpus is full of, so the filter this column exists for
(.emoji_rel_position > 0.8, "the emoji ends the message") skips every one
of them. emoji_ratio()'s .emoji_only finds that family of rows. One
character either side is enough to resolve the ambiguity the convention
settles: a trailing space scores the emoji 0, a leading one scores it
1, both on the ordinary path.
Positions are in logical (storage) order, not visual order. In a right-to-left script an emoji that is logically last renders at the reader's left, so "final" here means final in the string, not final on the screen.
See also
emoji_density() and emoji_ratio() for intensity metrics.
Examples
df <- data.frame(text = c("\U0001f600 leading", "trailing \U0001f600",
"none"))
emoji_position(df, text)
#> # A tibble: 3 × 5
#> text .emoji_n .emoji_first .emoji_last .emoji_rel_position
#> <chr> <int> <int> <int> <dbl>
#> 1 😀 leading 1 1 1 0
#> 2 trailing 😀 1 10 10 1
#> 3 none 0 NA NA NA