在 "data.table" 的 `fread` 函数中使用 `sep = "."`

8

如何让"data.table"中的fread使用"."作为sep值?

我正在尝试使用fread来加速"splitstackshape"中的concat.split函数。请参见this Gist以了解我所采用的一般方法,以及this question以了解我为什么想要进行切换。

我的问题是如何将点号(".")作为sep的值进行处理。每当我这样做时,就会出现“意外字符”的错误提示。

以下简化示例演示了该问题。

library(data.table)

y <- paste("192.168.1.", 1:10, sep = "")

x1 <- tempfile()
writeLines(y, x1)
fread(x1, sep = ".", header = FALSE)
# Error in fread(x1, sep = ".", header = FALSE) : Unexpected character (
# 192) ending field 2 of line 1

我当前函数中的解决方法是将"."替换为另一个字符,希望该字符不在原始数据中出现,例如"|",但这种方法对我来说似乎有风险,因为我无法预测其他人的数据集中会出现什么。以下是解决方法的示例。
x2 <- tempfile()
z <- gsub(".", "|", y, fixed=TRUE)
writeLines(z, x2)
fread(x2, sep = "|", header = FALSE)
#      V1  V2 V3 V4
#  1: 192 168  1  1
#  2: 192 168  1  2
#  3: 192 168  1  3
#  4: 192 168  1  4
#  5: 192 168  1  5
#  6: 192 168  1  6
#  7: 192 168  1  7
#  8: 192 168  1  8
#  9: 192 168  1  9
# 10: 192 168  1 10

为了回答这个问题,假设数据是平衡的(每一行都有相同数量的“sep”字符)。我知道使用“.”作为分隔符不是最好的选择,但我只是想考虑其他用户可能在他们的数据集中有什么,基于我在SO上回答过的其他 问题 链接


我还没有仔细查看fread的源代码,所以不想问显而易见的问题,但是你尝试过转义\\.了吗? - Ricardo Saporta
@RicardoSaporta,是的。您会收到以下错误消息:Error in fread(x1, sep = "\\.", header = FALSE) : 'sep' must be 'auto' or a single character - A5C1D2H2I1M1N2O1R2T1
我刚刚注意到我的评论。嗯...我不知道。也许@MattDowle可以发表意见? - Ricardo Saporta
@RicardoSaporta,这正是我所希望的 - 然后我也可以问他是否fread会支持像read.table一样的text参数 :) - A5C1D2H2I1M1N2O1R2T1
我不确定这是否应该被视为4列或2列(双精度),但无论哪种方式都似乎是一个错误 - 提交错误报告? - eddi
如果sep“字符”允许是多个字符的字符串,则可以通过z <- gsub(“。”,“|||||”,y,fixed = TRUE)使您的解决方法更加健壮。fread(x2,sep =“|||||”,header = FALSE) - Dean MacGregor
2个回答

3

现在已经在GitHub的v1.9.5版本中实施。

> input = paste( paste("192.168.1.", 1:5, sep=""), collapse="\n")
> cat(input,"\n")
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5 

sep='.'设置会导致新参数dec(默认值为'.')存在歧义:

> fread(input,sep=".")
Error in fread(input, sep = ".") : 
  The two arguments to fread 'dec' and 'sep' are equal ('.')

因此,选择其他东西来代替 dec
> fread(input,sep=".",dec=",")
    V1  V2 V3 V4
1: 192 168  1  1
2: 192 168  1  2
3: 192 168  1  3
4: 192 168  1  4
5: 192 168  1  5

您可能会收到一个警告:
> fread(input,sep=".",dec=",")
     V1  V2 V3 V4
 1: 192 168  1  1
 2: 192 168  1  2
 3: 192 168  1  3
 4: 192 168  1  4
 5: 192 168  1  5
Warning message:
In fread(input, sep = ".", dec = ",") :
  Run again with verbose=TRUE to inspect... Unable to change to a locale
  which provides the desired dec. You will need to add a valid locale name
  to getOption("datatable.fread.dec.locale"). See the paragraph in ?fread.

要么忽略或抑制警告,要么阅读该段落并设置选项:
options(datatable.fread.dec.locale = "fr_FR.utf8")

这可以确保没有歧义。


0

这个问题似乎与文本本身的数值有关:

library(data.table)

y <- paste("Hz.BB.GHG.", 1:10, sep = "")

xChar <- tempfile()
writeLines(y, xChar)
fread(xChar, sep = ".", header = FALSE)
#     V1 V2  V3 V4
#  1: Hz BB GHG  1
#  2: Hz BB GHG  2
#  3: Hz BB GHG  3
#  4: Hz BB GHG  4
#  5: Hz BB GHG  5
#  6: Hz BB GHG  6
#  7: Hz BB GHG  7
#  8: Hz BB GHG  8
#  9: Hz BB GHG  9
# 10: Hz BB GHG 10

然而,尝试使用原始值仍然会出现相同的错误:

fread(x1, sep = ".", header = FALSE, colClasses="numeric", verbose=TRUE)
fread(x1, sep = ".", header = FALSE, colClasses="character", verbose=TRUE)

 Detected eol as \n only (no \r afterwards), the UNIX and Mac standard.
 Looking for supplied sep '.' on line 10 (the last non blank line in the first 'autostart') ... found ok
 Found 4 columns
 First row with 4 fields occurs on line 1 (either column names or first row of data)
 Error in fread(x1, sep = ".", header = FALSE, colClasses = "character",  : 
   Unexpected character (192.) ending field 2 of line 1

然而,这个确实有效:

read.table(x1, sep=".")
#     V1  V2 V3 V4
# 1  192 168  1  1
# 2  192 168  1  2
# 3  192 168  1  3
# 4  192 168  1  4
# ... <cropped>

嗯,这很有趣。顺带一提,如果我们有 y <- paste("Hz.BB.GHG.", 1:10, 11:20, sep = ""),同样会出现错误。你知道为什么吗? - A5C1D2H2I1M1N2O1R2T1
1
伦敦现在已经快七点了,我不知道Matt为什么不在Stack Overflow上;祝你好运,我要去睡觉了(明天早上我会删除这个回答)。 - Ricardo Saporta
1
我猜测数字值的问题在于它假定 . 是一个小数点。 - A5C1D2H2I1M1N2O1R2T1
@AnandaMahto,fread(x1, sep = ".", header = FALSE, colClasses="numeric", verbose=TRUE)在我的电脑上(使用data.table 1.8.10)可以正常工作。另外,如果fread(x1, sep = ".", header = FALSE)已经能够同时适用于你们两个人,那么真正的问题是什么呢? - Michele
@Michele,你是指Ricardo回答中的x1还是我的问题中的x1?Ricardo,我正在编辑你的答案以避免混淆。 - A5C1D2H2I1M1N2O1R2T1
显示剩余4条评论

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