从数据文件中删除非 ASCII 字符

Posted

技术标签:

【中文标题】从数据文件中删除非 ASCII 字符【英文标题】:Removing non-ASCII characters from data files 【发布时间】:2012-04-13 15:49:33 【问题描述】:

我有一堆 csv 文件,我正在读入 R 并包含在 .rdata 格式的包/数据文件夹中。不幸的是,数据中的非 ASCII 字符无法通过检查。 tools 包有两个函数来检查非 ASCII 字符(showNonASCIIshowNonASCIIfile),但我似乎找不到一个来删除/清理它们。

在我探索其他 UNIX 工具之前,最好在 R 中完成这一切,这样我就可以维护从原始数据到最终产品的完整工作流程。是否有任何现有的包/功能可以帮助我摆脱非 ASCII 字符?

【问题讨论】:

尝试使用正则表达式,例如函数 gsub。检查 ?regexp 您知道read.csv() 接受encoding 参数,因此您可以处理这些,至少在R 中?非 ASCII 字符失败的具体检查是在 R 中(如果在此处发布)还是在外部? 【参考方案1】:

现在,稍微好一点的方法是使用 stringi 包,它提供了通用 unicode 转换的功能。这可以让您尽可能地保留原始文本:

x <- c("Ekstr\u00f8m", "J\u00f6reskog", "bi\u00dfchen Z\u00fcrcher")
x
#> [1] "Ekstrøm"         "Jöreskog"        "bißchen Zürcher"

stringi::stri_trans_general(x, "latin-ascii")
#> [1] "Ekstrom"          "Joreskog"         "bisschen Zurcher"

【讨论】:

任何想法如何使它与 stringi 一起工作 -- iconv("Klinik. der Univ. zu K_ln (AA\u0090R)","latin1","ASCII",sub="") =&gt; [1] "Klinik. der Univ. zu K_ln (AAR)"stringi::stri_trans_general("Klinik. der Univ. zu K_ln (AA\u0090R)", "latin-ascii") =&gt; [1] "Klinik. der Univ. zu K_ln (AA\u0090R)" stringi::stri_trans_general(x, "latin-ascii") 删除了我的文本中的一些非 ASCII 字符,但没有删除其他字符。 tools::showNonASCII 显示未删除的字符有:零宽度空格、商标符号、欧元符号、狭窄的不间断空格。这是否意味着 "latin-ascii" 是我的字符串的错误转换标识符?有没有一种简单的方法来找出正确的转换标识符?谢谢【参考方案2】:

要简单地删除非 ASCII 字符,您可以使用基本 R 的 iconv(),设置 sub = ""。像这样的东西应该可以工作:

x <- c("Ekstr\xf8m", "J\xf6reskog", "bi\xdfchen Z\xfcrcher") # e.g. from ?iconv
Encoding(x) <- "latin1"  # (just to make sure)
x
# [1] "Ekstrøm"         "Jöreskog"        "bißchen Zürcher"

iconv(x, "latin1", "ASCII", sub="")
# [1] "Ekstrm"        "Jreskog"       "bichen Zrcher"

定位非 ASCII 字符,或查找文件中是否有任何字符,您可能会采用以下想法:

## Do *any* lines contain non-ASCII characters? 
any(grepl("I_WAS_NOT_ASCII", iconv(x, "latin1", "ASCII", sub="I_WAS_NOT_ASCII")))
[1] TRUE

## Find which lines (e.g. read in by readLines()) contain non-ASCII characters
grep("I_WAS_NOT_ASCII", iconv(x, "latin1", "ASCII", sub="I_WAS_NOT_ASCII"))
[1] 1 2 3

【讨论】:

【参考方案3】:

要删除所有包含非 ascii 字符的单词(从 @Hadley 借用代码),您可以使用包 xfun 和来自 dplyrfilter

x <- c("Ekstr\u00f8m", "J\u00f6reskog", "bi\u00dfchen Z\u00fcrcher", "alex")
x

x %>% 
  tibble(name = .) %>%
  filter(xfun::is_ascii(name)== T)

【讨论】:

【参考方案4】:

我经常遇到 iconv 问题,而且我是 R 的基础粉丝。

所以我使用 gsub 代替 remove unicode 或非 ASCII,使用 lapply 将其应用于整个数据帧。

gsub("[^\u0001-\u007F]+|<U\\+\\w+>","", string)

这个 gsub 的好处是它可以匹配一系列符号格式。下面我展示了这两种模式的个别匹配。

x1 <- c("Ekstr\xf8m", "J\xf6reskog", "bi\xdfchen Z\xfcrcher")
gsub("[^\u0001-\u007F]+","", x1)
## "Ekstrm"        "Jreskog"       "bichen Zrcher"
x2 <- c("Ekstr\u00f8m", "J\u00f6reskog", "bi\u00dfchen Z\u00fcrcher")
gsub("[^\u0001-\u007F]+","", x2)
## Same as x1
## "Ekstrm"        "Jreskog"       "bichen Zrcher"
x3 <- c("<U+FDFA>", "1<U+2009>00", "X<U+203E>")
gsub("<U\\+\\w+>","", x3)
## ""    "100" "X"

【讨论】:

【参考方案5】:

textclean::replace_non_ascii() 为我完成了这项工作。此功能不仅可以删除特殊字母,还可以删除欧元、商标和其他符号。

    x <- c("Ekstr\u00f8m \u2605", "J\u00f6reskog \u20ac", "bi\u00dfchen Z\u00fcrcher \u2122")

 stringi::stri_trans_general(x, "latin-ascii")
    [1] "Ekstrom ★"          "Joreskog €"         "bisschen Zurcher ™"
    
textclean::replace_non_ascii(x)
    [1] "Ekstrom"               "Joreskog"              "bisschen Zurcher cent"

【讨论】:

以上是关于从数据文件中删除非 ASCII 字符的主要内容,如果未能解决你的问题,请参考以下文章

从 Oracle Varchar2 中查找和删除非 ASCII 字符

如何使用正则表达式和 Notepad++ 删除所有非 ASCII 字符?

如何从字符串中删除非 ASCII 字符?

从 Snowflake 中的字符串中删除非 ASCII 字符

从文本文件中读取非 ASCII 字符

DB2 到 SQL 链接服务器 OpenQuery 非 Ascii 字符问题