在R中从数据框列中删除重音。

43

我有一个data.table基础。 在这个data.table中,我有一个term列。

class(base$term)
[1] character
length(base$term)
[1] 27486

我可以从一个字符串中删除重音符号。 我可以从一个字符串向量中删除重音符号。

iconv("Millésime",to="ASCII//TRANSLIT")
[1] "Millesime"
iconv(c("Millésime","boulangère"),to="ASCII//TRANSLIT")
[1] "Millesime" "boulangere"

但出于某些原因,当我将同样的函数应用到我的术语列时,它却不起作用。

base$terme[2]
[1] "Millésime"
iconv(base$terme[2],to="ASCII//TRANSLIT")
[1] "MillACsime"

有人知道这里发生了什么吗?


是因为 base$terme 是一个因子吗?尝试先转换为 character 或者转换水平(levels)也许会有帮助。 - NJBurgo
根据第一个输出(假设是打字错误),它的类型为“字符”。 - Konrad Rudolph
2
小心:您的向量结果完全不同:“[1]“Mill'esime”“boulangere””。 iconv文档指定TRANSLIT`在不同系统上会产生不同的结果(这当然有点无用)。 - Konrad Rudolph
尝试使用 iconv(base$terme[2], from="latin1", to="ASCII//TRANSLIT")。如果不行,请提供 Encoding(base$terme[2]) 的输出结果。 - nicola
嗨,尼古拉,Encoding(base$terme[2])的输出是“UTF-8”。 - hans glick
8个回答

50

使用包可能更容易。这样,您无需预先检查编码。此外,在各种操作系统中保持一致,而iconv则不具备该特性。

library(stringi)
 
base <- data.table(terme = c("Millésime", 
                             "boulangère", 
                             "üéâäàåçêëèïîì"))

base[, terme := stri_trans_general(str = terme, 
                                   id = "Latin-ASCII")]
 
> base
           terme
1:     Millesime
2:    boulangere
3: ueaaaaceeeiii

1
这是唯一对我起作用的方法,非常感谢! - Janus De Bondt
这是唯一对我有效的方法。但是,如果有人想修复以下代码=> ds_itens$content <- iconv(ds_itens$content, 'utf-8', 'ascii', sub = '') 就太好了。这段最后的代码几乎达到了100%。 - Luis

37

好的,解决问题的方法:

Encoding(base$terme[2])
[1] "UTF-8"
iconv(base$terme[2],from="UTF-8",to="ASCII//TRANSLIT")
[1] "Millesime"

感谢 @nicola


13

这里是Jeldrik的解决方案的一个版本,针对数据框进行了修订。请注意,:=运算符在基础R中已被弃用。

library(stringi)

base <- data.frame(terme = c("Millésime", 
                             "boulangère", 
                             "üéâäàåçêëèïîì"))

base$terme = stri_trans_general(str = base$terme, id = "Latin-ASCII")

3

以下是三种去除重音符号的方法,它们将被展示并相互比较。
用于演示的数据:

dtCases <- fread("https://raw.githubusercontent.com/ccodwg/Covid19Canada/master/retired_datasets/individual_level/cases_2021_1.csv", stringsAsFactors = F )
dim(dtCases) #  751526     16

基准测试:

> system.time(dtCases [, city0 := health_region])
   user  system elapsed 
  0.009   0.001   0.012 
> system.time(dtCases [, city1 := base::iconv (health_region, to="ASCII//TRANSLIT")]) # or ... iconv (health_region, from="UTF-8", to="ASCII//TRANSLIT")
   user  system elapsed 
  0.165   0.001   0.200 
> system.time(dtCases [, city2 := textclean::replace_non_ascii (health_region)])
   user  system elapsed 
  9.108   0.063   9.351 
> system.time(dtCases [, city3 := stringi::stri_trans_general (health_region,id = "Latin-ASCII")])
   user  system elapsed 
   4.34    0.00    4.46 

结果:

> dtCases[city0!=city1, city0:city3] %>% unique
                           city0                         city1                         city2                         city3
                          <char>                        <char>                        <char>                        <char>
1:                      Montréal                      Montreal                      Montreal                      Montreal
2:                    Montérégie                    Monteregie                    Monteregie                    Monteregie
3:          Chaudière-Appalaches          Chaudiere-Appalaches          Chaudiere-Appalaches          Chaudiere-Appalaches
4:                    Lanaudière                    Lanaudiere                    Lanaudiere                    Lanaudiere
5:                Nord-du-Québec                Nord-du-Quebec                Nord-du-Quebec                Nord-du-Quebec
6:         Abitibi-Témiscamingue         Abitibi-Temiscamingue         Abitibi-Temiscamingue         Abitibi-Temiscamingue
7: Gaspésie-Îles-de-la-Madeleine Gaspesie-Iles-de-la-Madeleine Gaspesie-Iles-de-la-Madeleine Gaspesie-Iles-de-la-Madeleine
8:                     Côte-Nord                     Cote-Nord                     Cote-Nord                     Cote-Nord

结论:

base::iconv() 是最快速和首选的方法。 在法语单词上测试过,未在其他语言上进行过测试。


3
您可以应用此函数。
    rm_accent <- function(str,pattern="all") {
   if(!is.character(str))
    str <- as.character(str)

  pattern <- unique(pattern)

  if(any(pattern=="Ç"))
    pattern[pattern=="Ç"] <- "ç"

  symbols <- c(
    acute = "áéíóúÁÉÍÓÚýÝ",
    grave = "àèìòùÀÈÌÒÙ",
    circunflex = "âêîôûÂÊÎÔÛ",
    tilde = "ãõÃÕñÑ",
    umlaut = "äëïöüÄËÏÖÜÿ",
    cedil = "çÇ"
  )

  nudeSymbols <- c(
    acute = "aeiouAEIOUyY",
    grave = "aeiouAEIOU",
    circunflex = "aeiouAEIOU",
    tilde = "aoAOnN",
    umlaut = "aeiouAEIOUy",
    cedil = "cC"
  )

  accentTypes <- c("´","`","^","~","¨","ç")

  if(any(c("all","al","a","todos","t","to","tod","todo")%in%pattern)) # opcao retirar todos
    return(chartr(paste(symbols, collapse=""), paste(nudeSymbols, collapse=""), str))

  for(i in which(accentTypes%in%pattern))
    str <- chartr(symbols[i],nudeSymbols[i], str) 

  return(str)
}

3
iconv 不同,这个方法没有矢量化并且不涵盖所有可能性。 - Leonardo Siqueira

2

快速、简单、易于修改,无依赖:

# -----------------------------------------------------------------------------
# Removes common accents from letters.
#
# @param s The string to remove diacritics from.
# -----------------------------------------------------------------------------
accentless <- function( s ) {
  chartr(
    "áéóūáéíóúÁÉÍÓÚýÝàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛãõÃÕñÑäëïöüÄËÏÖÜÿçÇ",
    "aeouaeiouAEIOUyYaeiouAEIOUaeiouAEIOUaoAOnNaeiouAEIOUycC",
    s );
}

2

基于jf2017代码,这里提供了一个tidyverse解决方案:

library(dplyr)    
base %>%
   # latin-ASCII-free "term" column (careful: this overwrites the original "term" column!)
   mutate(term = stringi::stri_trans_general(str = term, id = "Latin-ASCII")

要应用于数据框中的所有列,请使用

base %>%
mutate(across(.cols = everything(),
              .fns = ~ stringi::stri_trans_general(., id = "Latin-ASCII")))

运行stringi::stri_trans_list()来查看id可以使用的所有可用参数


1

在我的电脑上,iconv 选项无法正常工作,但我使用 textclean 包中的 replace_non_ascii 函数解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接