• R语言
  • R4.2编译包中文乱码自定义编码问题

我在win 10的R 4.2.0版本以上,也经历类似的困惑。比如,csv格式保存的数据,经过Excel修改后,默认中文编码为ANSI,用R的read.csv()打开就会出错。
我的临时解决方法是,打开.Rprofile,在全局环境中自定义函数read.csv。

file.edit(file.path("~", ".Rprofile"))
read.csv <- function(file) {
    . <- try(read.csv(file = file), silent = T)
    if(inherits(., "try-error")) {
    . <- read.csv(file(description = file, encoding = "GB18030"))
    }
    .
}

另外,我有点疑惑的是,这应该是一个普遍存在的问题,为什么很少人提问呢?

    wangbinzjcc 这应该是一个普遍存在的问题,为什么很少人提问呢?

    “普遍”是相对的,要看你定义的总体是什么了。R 的核心开发者几乎都是英语母语,据我所知 Windows 的人可能只有一位。他们知道字符编码问题的痛苦,但一是他们自己很难遇到这种问题,二是他们也难以测试,三是 Windows 本身的废柴,直到几年前(两年?)才开始原生支持 UTF-8,所以这问题花了这么多年才在 R 4.2.0 中最终得以解决。

    你这个办法倒也是个办法,但最终我还是建议一切文本文件使用 UTF-8 编码保存。另外你的代码可以稍微简化一下:

    read.csv <- function(...) {
      tryCatch(utils::read.csv(...), error = function(e) {
        utils::read.csv(..., fileEncoding = "GB18030")
      })
    }

    earclimateR 1)R4.2发布后声称彻底解决windows下的字体编码问题,支持原生UTF-8,问题是不再支持GBK了吗?

    依旧支持。只要你读取文件时指定编码即可(如果用来读取的函数支持指定编码的话)。

    earclimateR 有没有办法让RData文件以GBK的形式进行编译?

    我估计没有,至少会很难,我建议你用 iconv(..., from = "GBK", to = "UTF-8") 将原来的字符串转成 UTF-8 编码。这应该是可以写几句代码批量完成的。

      yihui 多谢您对代码的精简。看来还是要勇敢暴露自己的代码,这样才有机会被优化。群众的眼睛是雪亮的,行家的眼睛更是雪亮的。

      国内同时使用windows的excel和R的用户,很多。数据读取频繁报错的话,增加了新用户使用R的难度。

        函数read.csv属于utils包

        read.csv <- function(...) {
          tryCatch(utils::read.csv(...), error = function(e) {
            utils::read.csv(..., fileEncoding = "GB18030")
          })
          }

        yihui 谢谢益辉亲自出来解惑,没想到把您老人家炸出来了,说明这个问题您也认为很普遍,有必要澄清吧 😀
        其实我是R的深度用户,十年前因为经常在魏公村附近转悠,跟着您和论坛入门了R,但我面对4.2的版本,仍然想不到很好的策略,上论坛时发现帐号密码都忘记了,新注册了个马甲,可见4.2后中文环境的使用,需要为国内用户讨论出一些策略建议。

        比如@wangbinzjcc提到的数据文件读取问题(我看他也是10年前的注册用户了)。在日常场景中,我们使用的业务数据或外部数据一般不会是UTF-8的编码,您建议一切文本文件用UTF-8保存不太现实吧,可能更适合用指定GBK读取的方式,这可能涉及许多诸如read.table, read.csv, data.table::fread以及GIS相关的读取矢量数据的函数等等,我曾经封装过很多函数,可以想象要把原来的程序升级到4.2版本还是有点工作量(主要是怕遗漏)。

        第二个问题是关于原来GBK下保存的Rdata数据,您提议通过iconvs来转换,我准备采纳了。计划的处理流程是,在编译前对包中可能载入的所有data,检测是否存在乱码,存在乱码的话对列名(非数值变量的各列做编码转换),原来没这么转换一是嫌麻烦,二是怕来回转换后会不会产生一些转换失败的NA。

        最后,还是期待社区能出一些工具或策略,比如通过options(encoding=”GBK”)或某些基础包来支持GBK下的工作场景,让国内用户能够无感切换。

          earclimateR

          有比我更年轻的同事问我: "为什么我之前能运行的代码,现在运行不了呀?"
          我的解答是: "退回到之前的R版本,可以在Rstudio的某某某某里面选择。"
          然后得到称赞: “哇,果然可以运行了,你好厉害呀。”

          我中途也有段时间,登录不了账号。导致有了两个账号。经过你的提醒我才想起来这回事。
          不知道怎样才能把其中一个账号注销到,释放出来常用的QQ邮箱 。

          earclimateR 说明这个问题您也认为很普遍,有必要澄清吧

          是的,对中日韩用户来说,极其普遍。我们都苦编码问题久矣(“久” == 十几年)。

          earclimateR 上论坛时发现帐号密码都忘记了,新注册了个马甲,可见4.2后中文环境的使用,需要为国内用户讨论出一些策略建议

          原来是老坛友了。密码忘了应该是可以通过邮箱找回的吧。如果邮箱也忘了,可以联系我们。是的,需要为国内用户提供策略。

          earclimateR 我们使用的业务数据或外部数据一般不会是UTF-8的编码,您建议一切文本文件用UTF-8保存不太现实吧,可能更适合用指定GBK读取的方式

          嗯,我不了解情况,有可能是站着说话不腰疼,不知道工作量有多大。如果数据都是 GBK 编码的文本文件,那么转码应该是可以批量搞定的:

          gbk2utf8 = function(input, output) {
            con = file(input, encoding = 'GBK')
            txt = readLines(con)
            writeLines(enc2utf8(txt), output, useBytes = TRUE)
          }

          也可以用命令行工具 iconv。要不然就是不动数据,但在读数据的函数中加上编码参数,如 read.csv(..., fileEncoding = 'GBK')

          earclimateR 二是怕来回转换后会不会产生一些转换失败的NA

          如果从 GBK 转 UTF-8 产生 NA,那就说明原字符串不是 GBK 编码。这种情况下你可以加个判断并停止,仔细检查一下原字符串到底是怎么回事。

          earclimateR 还是期待社区能出一些工具或策略,比如通过options(encoding=”GBK”)或某些基础包来支持GBK下的工作场景,让国内用户能够无感切换

          我猜 options(encoding = 'GBK') 是可以的,但是这个选项设置最好不要全局设置,而是在读数据的时候临时设定一下,读完就恢复出厂设置,不然这个选项可能会带来很多意想不到的副作用。

            yihui 谢谢哈,已经给出很具体的建议了!这种接近语言底层的技术问题只有像您这样的开发者解答才能让大家信服,否则总是在幻想是不是还有更好的解决方案。但是我对于4.2后中文环境下的使用还是耿耿于怀 😅 我期待有一种类似options或Sys.setlocale的全局设置能像4.1一样至少在使用时没那么多啰嗦的编码设置问题(原来只是编译包时存在障碍),现在编码问题直接暴露在任何等级的R用户面前,初学者会发现哎读个中文路径的文件都到处是陷阱,上来就要先了解编码的坑,对用户来说反而不友好了@wangbinzjcc

              earclimateR 但是我对于4.2后中文环境下的使用还是耿耿于怀 😅 我期待有一种类似options或Sys.setlocale的全局设置能像4.1一样至少在使用时没那么多啰嗦的编码设置问题

              这是长痛之后不可避免的一个短痛,痛完这一次就解放了,因为 UTF-8 一统天下(Linux 世界早就如此了),再也不用对编码猜猜猜,猜编码简直让程序猿少活了几年(浪费时间等于浪费生命)。当然,对历史遗留下来的各种非 UTF-8 编码文件还需要处理,但也只是一次性处理。大一统之前,总是会有大痛苦的。

                1 年 后

                earclimateR
                如果你用reticulate包,引入python环境的包和环境时,存储Rdata数据文件时,会有异常,这个方法只适用于R环境内的变量和数据。引入python的环境变量时,这个python内的数据、变量不会被同时在此文件内复现。