为啥 R 将 UTF-8 标头作为文本读取?
Posted
技术标签:
【中文标题】为啥 R 将 UTF-8 标头作为文本读取?【英文标题】:Why is R reading UTF-8 header as text?为什么 R 将 UTF-8 标头作为文本读取? 【发布时间】:2013-11-25 01:06:13 【问题描述】:我将 Excel 表格保存为文本 (*.txt)。不幸的是,Excel 不允许我选择编码。所以我需要在记事本中打开它(以 ANSI 格式打开)并将其保存为 UTF-8。然后,当我在 R 中阅读它时:
data <- read.csv("my_file.txt",header=TRUE,sep="\t",encoding="UTF-8")
它显示以“X.U.FEFF.”开头的第一列的名称。我知道这些是为告诉任何程序文件是 UTF-8 格式而保留的字节。所以它不应该显示为文本!这是一个错误吗?还是我错过了一些选择?提前致谢!
【问题讨论】:
尝试使用read.csv
参数check.names=FALSE
。请注意,如果您使用它,您将无法使用 $
表示法直接引用列。
UTF-8 文件不应该包含字节顺序标记,请参阅RFC 3629 以获得解释。
谢谢@Matthew。它部分工作。 X.U.FEFF 不见了,但我不能再按名称引用第一列(尽管其他列仍然有效)。我仍然认为这是 R 未来版本中需要解决的错误。
如果你把它们放在引号里,你可以通过名字来引用它们,例如,yourdf$"first col"
@Zack,我见过一些带有这些第一个字节的 UTF-8 文件,所以我认为这是一个规则。不是什么大问题,因为我总是可以重命名第一列,只是认为它应该有一天会解决。
【参考方案1】:
read.csv
中的大多数参数都是虚拟参数——包括fileEncoding
。
改用read.table
read.table("my_file.txt", header=TRUE, sep="\t", fileEncoding="UTF-8")
【讨论】:
使用 read.table 我收到一个错误:“扫描错误(文件,内容,nmax,sep,dec,quote,skip,nlines,na.strings,:第 9191 行没有 25 个元素"。我的阅读评论其实比较复杂,就是:data 太棒了!然后它起作用了。现在你只需要清理你的源文件;)在纯文本编辑器中打开它(我喜欢 sublime text 3),到第 9191 行并检查它 谢谢,@Ricardo。我只需要comment.char=""。但现在它的行为与 read.csv 完全相同... :(【参考方案2】:来自 cmets 的可能解决方案:
尝试使用 read.csv 参数 check.names=FALSE
。请注意,如果您使用它,您将无法使用 $
表示法直接引用列,除非您将名称括在引号中。例如:yourdf$"first col"
。
【讨论】:
【参考方案3】:所以我打算向您说明如何手动打开文件并检查和丢弃 BOM,但后来我注意到了这一点(?file
):
从 R 3.0.0 开始,编码“UTF-8-BOM”被接受,并将 如果存在,则删除字节顺序标记(通常用于文件 和由 Microsoft 应用程序生成的网页)。
这意味着如果你有一个足够新的 R 解释器,
read.csv("my_file.txt", fileEncoding="UTF-8-BOM", ...other args...)
应该做你想做的。
【讨论】:
嗯嗯差不多了。现在是“X.U.FEFF”。变成了“我..” 看起来该文件实际上不是 UTF-8。有什么方法可以向我们展示文件第一行的十六进制转储? (在大多数 Unix 系统上,head -1 my_file.txt | hexdump -C
会给你一个很好的十六进制转储,但我不知道 Windows 等价物。)
在 DOS 提示符下,调试会执行此操作。前三个字节是 EF BB BF。 (我将文件保存在记事本 5.1 build 2600、Windows XP SP3 中,它说格式是 UTF-8)。该行的其余部分是列名的 ASCII。
EF BB BF 43 4F 4C 45 43 41 4F 09
是的,我有 R 3.0.1。我下载了 Notepad++,它让我可以选择在有和没有 BOM 的情况下进行保存。似乎 R 无法处理 BOM。【参考方案4】:
我在使用read.csv
(使用encoding="UTF-87-BOM"
)、read.table
或read_csv
从readr
包加载csv 文件时遇到了同样的问题。这些尝试都没有成功。
我绝对不能使用 BOM 标记,因为在子设置我的数据时(使用两种方法 subset()
或 df[df$var=="value",]
),第一行没有被考虑在内。
我终于找到了使 BOM 标记消失的解决方法。使用 read.csv
函数,我刚刚在参数 col.names = ...
中为我的列名定义了一个字符串向量。这就像一个魅力,我可以毫无问题地对我的数据进行子集化。
我使用 R 版本 3.5.0
【讨论】:
以上是关于为啥 R 将 UTF-8 标头作为文本读取?的主要内容,如果未能解决你的问题,请参考以下文章