为什么在操作字符串时stringr会改变编码?

时间:2015-11-02 16:27:19

标签: r encoding data.table stringr

stringr有这种奇怪的行为,这真让我烦恼。 stringr在没有警告的情况下更改包含异国字符的某些字符串的编码,在我的情况下ø,å,æ,é和其他一些......如果你str_trim是一个字符矢量,那么那些异国情调的字母将被转换为新的编码。

letter1 <- readline('Gimme an ASCII character!')     # try q or a
letter2 <- readline('Gimme an non-ASCII character!') # try ø or é
Letters <- c(letter1, letter2)
Encoding(Letters)           # 'unknown'
Encoding(str_trim(Letters)) # mixed 'unknown' and 'UTF-8'

这是一个问题,因为我使用data.table来快速合并大表,而data.table不支持混合编码,因为我找不到回归统一编码的方法。

任何解决方法?

编辑:我认为我可以回到基本功能,但他们不保护编码。 paste保留了它,但不是sub

 Encoding(paste(' ', Letters))                 # 'unknown'
 Encoding(str_c(' ', Letters))                 # mixed
 Encoding(sub('^ +', '', paste(' ', Letters))) # mixed

3 个答案:

答案 0 :(得分:3)

stringr正在更改编码,因为stringrstringi包的包装,stringi始终以UTF-8编码。有关详细信息和此设计选择的说明,请参阅help("stringi-encoding", package = "stringi")

为了避免合并data.table的问题,请确保所有id变量都以UTF-8编码。您可以使用stri_enc_toutf8包中的stringi或使用iconv来执行此操作。

答案 1 :(得分:2)

使用this recent commit,data.table现在可以通过在创建data.tables时确保正确的编码以及确保unique()和{{1}等函数中的正确编码来隐式处理这些混合编码}}

请参阅README.md中v1.9.7的错误下的新闻第(23)项。

如果您遇到任何进一步的问题,请测试并回复。

答案 2 :(得分:1)

R并不总是能够轻松地在编码之间进行转换(这里有函数iconv但是这个函数接受的是平台相关的)。但是,至少可以将字符串的编码标记重置为“unknown”:

Letters = str_trim(Letters)
Encoding(Letters)
# [1] "unknown" "UTF-8"
Encoding(Letters) = ''
Encoding(Letters)
# [1] "unknown" "unknown"

但是,请注意,这只标记字符串的编码,它实际上并不重新编码字符串。结果,这可能导致数据乱码。正如评论中所提到的,这至多是一个黑客,而不是问题的实际修复。

Encoding举例说明了R在编码方面正常工作的麻烦。文档说:

  

ASCII字符串永远不会使用声明的编码进行标记,因为它们在所有支持的编码中的表示形式相同。

...这显然没有任何帮助(而且还有一点误导;仅由代码点&lt; 128组成的UTF-8字符串可能看起来与ASCII字符串无法区分,但对其进行操作会产生不同的结果,具体取决于编码,这就是应该有效标记的原因。)

有趣的是,enc2nativeenc2utf8都不会在此处执行所需的操作 - 两者都会以Letters中的两个字符串生成不同的编码,这是Encoding的直接后果上面提到的问题。