【问题标题】:Using sep = "." in `fread` from "data.table"使用 sep = "."在“data.table”的“fread”中
【发布时间】:2013-10-14 21:13:45
【问题描述】:

是否可以强制“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”字符)。我知道使用"." 作为分隔符不是最好的主意,但我只是想根据other questions I've answered 来解释其他用户在他们的数据集中可能拥有的内容。所以。

【问题讨论】:

  • 我没怎么看fread的来源,所以不要问显而易见的问题,但是您是否尝试过转义\\.
  • @RicardoSaporta,是的。你会得到一个错误:Error in fread(x1, sep = "\\.", header = FALSE) : 'sep' must be 'auto' or a single character.
  • 我在发表评论后才注意到这一点。嗯...我不知道。也许@MattDowle 可以加入?
  • @RicardoSaporta,这就是我所希望的——然后我也可以问他fread 是否支持text 参数,如read.table 支持:)
  • 我不清楚这应该被读取为 4 列还是 2 列(双精度),但无论哪种方式似乎都是错误 - 提交错误报告?

标签: r data.table fread splitstackshape


【解决方案1】:

问题接缝与文本本身的数值有关:

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 &lt;- paste("Hz.BB.GHG.", 1:10, 11:20, sep = ""),我们又会得到一个错误。知道为什么吗?
  • 关于您的编辑 (read.table),这是我目前在 concat.split 的一个版本中使用的。见splitstackshape:::read.concat
  • 伦敦快早上 7 点了,我不知道 Matt 不在 stackoverflow 上做什么;)祝你好运,我要睡觉了(我会在早上删除这个答案)
  • 我猜数字值的问题在于它假定. 是小数。
  • 使用任何%+- 作为分隔符而不是. 工作正常。使用y &lt;- paste(".A.168.1.", 1:10, sep = "", collapse="\n"),即在开头加上一个额外的.,也会产生同样的错误,所以它可能根本与数值处理无关。在我的错误消息中,Unexpected character ( 之后有一个换行符,所以可能有一些非打印字符从某个地方爬进来?
【解决方案2】:

现已在 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")

这确保不会有歧义。

【讨论】:

    猜你喜欢
    • 2014-10-28
    • 2022-11-09
    • 2013-07-09
    • 1970-01-01
    • 2014-08-16
    • 2013-01-04
    • 2015-10-22
    • 2018-03-18
    • 1970-01-01
    相关资源
    最近更新 更多