如何使用 R 中的正则表达式删除字符串中表情符号的 Unicode 表示?
How to remove Unicode representations of Emojis in strings using regexp in R?
我正在处理来自 Twitter API 的数据,只要用户在其名称字段中包含表情符号,它们就会在我的数据框中转换为 Unicode 字符串表示形式。我的数据结构有点像这样:
user_profiles <- as.data.frame(c("Susanne Bold", "Julian K. Peard <U+0001F41C>",
"<U+0001F30A> Alexander K Miller <U+0001F30A>", "John Mason"))
colnames(user_profiles) <- "name"
看起来像这样:
name
1 Susanne Bold
2 Julian K. Peard <U+0001F41C>
3 <U+0001F30A> Alexander K Miller <U+0001F30A>
4 John Mason
我现在正尝试使用正则表达式将实际名称隔离到一个新列中:
user_profiles <- user_profiles %>%
mutate(clean_name = str_remove_all(name, "\<U\+[[:alnum:]]\>[ ]?"))
但是这个表达式 1. 看起来相当复杂并且 2. 不适用于识别模式。我已经尝试了正则表达式的多种变体,奇怪的是,grepl
能够检测到此版本的模式(string_remove_all
不接受,因为它缺少右括号):
grepl("\<U\+[[:alnum:]\>[ ]?", user_profiles$name)
[1] FALSE TRUE TRUE FALSE
# note that the second bracket around alnum is left opened
有人可以解释一下或提供更简单的解决方案吗?
非常感谢!
这里有一个替代方法:
library(dplyr)
library(tidyr)
user_profiles %>%
separate_rows(name, sep = '\<|\>') %>%
filter(!str_detect(name, 'U+')) %>%
mutate(name = na_if(name, "")) %>%
na.omit()
name
<chr>
1 "Susanne Bold"
2 "Julian K. Peard "
3 " Alexander K Miller "
4 "John Mason"
第一个 str_remove_all
不起作用,因为您错过了字母数字模式后的 +
量词。另外,请注意在 <U+
之后仅使用十六进制字符,因此您可以使用更精确的 [:xdigit:]
POSIX 字符 class 而不是 [:alnum:]
。 =44=]
你可以使用
user_profiles <- user_profiles %>%
mutate(clean_name = str_remove_all(name, "<U\+[[:xdigit:]]+>\s*"))
不要转义 <
和 >
,它们在任何正则表达式风格中都不是特殊的,并且在 TRE 正则表达式中,与没有 perl=TRUE
的基本正则表达式函数一起使用,\<
和 \>
是单词边界。
图案详情
<U
- <U
字符串
\+
- 文字 +
[[:xdigit:]]+
- 一个或多个十六进制字符
>
- 一个 >
字符
\s*
- 零个或多个白色spaces.
为什么 grepl
正则表达式有效 ?这很有趣,因为您省略了 ]
右括号表达式边界字符,并“破坏”了正则表达式以像这样匹配:
\<U\+
- 单词边界(在 TRE 中,\<
匹配 left-hand 单词边界)然后 U+
string
[[:alnum:]\>[ ]?
- 这是一个可选的括号表达式,匹配集合中的一个或零个字符:
[:alnum:]
- 任何字母数字字符
\
- 反斜杠(是的,因为在 TRE 正则表达式风格中,正则表达式转义序列按字面意思处理)
>
- 一个 >
字符
[
- 一个 [
字符
- 一个 space.
因此,它匹配 <U+0001F41C>
中的 <U+0
,例如。
我们可以为 [[:alnum:]]
添加一个或多个 (+
)
library(dplyr)
library(stringr)
user_profiles <- user_profiles %>%
mutate(clean_name = str_remove_all(name, "\s*\<U\+[[:alnum:]]+\>\s*"))
-输出
user_profiles
name clean_name
1 Susanne Bold Susanne Bold
2 Julian K. Peard <U+0001F41C> Julian K. Peard
3 <U+0001F30A> Alexander K Miller <U+0001F30A> Alexander K Miller
4 John Mason John Mason
我正在处理来自 Twitter API 的数据,只要用户在其名称字段中包含表情符号,它们就会在我的数据框中转换为 Unicode 字符串表示形式。我的数据结构有点像这样:
user_profiles <- as.data.frame(c("Susanne Bold", "Julian K. Peard <U+0001F41C>",
"<U+0001F30A> Alexander K Miller <U+0001F30A>", "John Mason"))
colnames(user_profiles) <- "name"
看起来像这样:
name
1 Susanne Bold
2 Julian K. Peard <U+0001F41C>
3 <U+0001F30A> Alexander K Miller <U+0001F30A>
4 John Mason
我现在正尝试使用正则表达式将实际名称隔离到一个新列中:
user_profiles <- user_profiles %>%
mutate(clean_name = str_remove_all(name, "\<U\+[[:alnum:]]\>[ ]?"))
但是这个表达式 1. 看起来相当复杂并且 2. 不适用于识别模式。我已经尝试了正则表达式的多种变体,奇怪的是,grepl
能够检测到此版本的模式(string_remove_all
不接受,因为它缺少右括号):
grepl("\<U\+[[:alnum:]\>[ ]?", user_profiles$name)
[1] FALSE TRUE TRUE FALSE
# note that the second bracket around alnum is left opened
有人可以解释一下或提供更简单的解决方案吗?
非常感谢!
这里有一个替代方法:
library(dplyr)
library(tidyr)
user_profiles %>%
separate_rows(name, sep = '\<|\>') %>%
filter(!str_detect(name, 'U+')) %>%
mutate(name = na_if(name, "")) %>%
na.omit()
name
<chr>
1 "Susanne Bold"
2 "Julian K. Peard "
3 " Alexander K Miller "
4 "John Mason"
第一个 str_remove_all
不起作用,因为您错过了字母数字模式后的 +
量词。另外,请注意在 <U+
之后仅使用十六进制字符,因此您可以使用更精确的 [:xdigit:]
POSIX 字符 class 而不是 [:alnum:]
。 =44=]
你可以使用
user_profiles <- user_profiles %>%
mutate(clean_name = str_remove_all(name, "<U\+[[:xdigit:]]+>\s*"))
不要转义 <
和 >
,它们在任何正则表达式风格中都不是特殊的,并且在 TRE 正则表达式中,与没有 perl=TRUE
的基本正则表达式函数一起使用,\<
和 \>
是单词边界。
图案详情
<U
-<U
字符串\+
- 文字+
[[:xdigit:]]+
- 一个或多个十六进制字符>
- 一个>
字符\s*
- 零个或多个白色spaces.
为什么 grepl
正则表达式有效 ?这很有趣,因为您省略了 ]
右括号表达式边界字符,并“破坏”了正则表达式以像这样匹配:
\<U\+
- 单词边界(在 TRE 中,\<
匹配 left-hand 单词边界)然后U+
string[[:alnum:]\>[ ]?
- 这是一个可选的括号表达式,匹配集合中的一个或零个字符:[:alnum:]
- 任何字母数字字符\
- 反斜杠(是的,因为在 TRE 正则表达式风格中,正则表达式转义序列按字面意思处理)>
- 一个>
字符[
- 一个[
字符
因此,它匹配 <U+0001F41C>
中的 <U+0
,例如。
我们可以为 [[:alnum:]]
+
)
library(dplyr)
library(stringr)
user_profiles <- user_profiles %>%
mutate(clean_name = str_remove_all(name, "\s*\<U\+[[:alnum:]]+\>\s*"))
-输出
user_profiles
name clean_name
1 Susanne Bold Susanne Bold
2 Julian K. Peard <U+0001F41C> Julian K. Peard
3 <U+0001F30A> Alexander K Miller <U+0001F30A> Alexander K Miller
4 John Mason John Mason