【问题标题】:read.table.ffdf ignores check.names when giving colClassesread.table.ffdf 在给出 colClasses 时会忽略 check.names
【发布时间】:2018-02-09 16:01:19
【问题描述】:

我正在尝试使用库 ff 中的 read.table.ffdf 方法读取一个相当大的文件。不幸的是,该表的列名包含空格、制表符和其他特殊字符。它看起来大致像这样(但有大约 400 列):

attribute_1;next attribute;who creates, these horrible) column&nämes
198705;RXBR ;2017-07-05 00:00:00

这不漂亮,我知道,但我不得不使用它,所以我必须将 check.names 设置为 FALSE。

此外,我正在生成一个包含列类类型的列表,我喜欢这样做:

path <- 'path_to_csv-file'
headset <- read.csv(path, sep= ';', dec= '.', header = TRUE, nrows = 2, check.names = FALSE)
#print(headset)
headclasses <- vector(mode = 'character', length = 0)


#heavily simplified version - switch_statement is  in an extra function
for(i in colnames(headset)){
  headclasses[[i]] <- switch (i,
                              'attribute_1' = 'numeric',
                              'next attribute' = 'factor',
                              'who creates, these horrible) column&nämes' = 'POSIXct'
                              )
}
#print(colnames(headset))
#print(headclasses)

现在,如果我打电话:

df <- read.table.ffdf(file=path, levels = NULL, appendLevels = TRUE, FUN = 'read.table', na.strings = c('\\N',''), sep= ';', dec= '.', colClasses = headclasses, check.names = FALSE , header = TRUE, nrows = 1e4, VERBOSE = TRUE)

我收到以下错误:

repnam(colClasses, colnames(x), default = NA) 中的错误: 以下参数名称不匹配'下一个属性','(谁创建,这些可怕的列&名称)'

为什么会出现此错误?以及如何解决它,以便我将丑陋的字符串作为列名?

注意,在之前的调用中,check.names 设置为 FALSE。

到目前为止我的工作:

1.调用 read.table.ffdf 时尝试使用正确的名称但错误的 check.names 选项

如果我让 R 选择正确的列名(即,在第一次调用读取方法时 check.names = TRUE)并相应地调整 switch 语句,即使我在 read.table.ffdf-method 中设置了 check.names = FALSE:

headset <- read.csv(path, sep= ';', dec= '.', header = TRUE, nrows = 2)
print(headset)
headclasses <- vector(mode = 'character', length = 0)


#heavily simplified version - switch_statement is  in an extra function
for(i in colnames(headset)){
  headclasses[[i]] <- switch (i,
                              'attribute_1' = 'numeric',
                              'next.attribute' = 'factor',
                              'who.creates..these.horrible..column.nämes' = 'POSIXct'
                              )
}
print(colnames(headset))
print(headclasses)

my_df <- read.table.ffdf(file=path, levels = NULL, appendLevels = TRUE, FUN = 'read.table', na.strings = c('\\N',''), sep= ';', dec= '.', colClasses = headclasses, check.names = FALSE , header = TRUE, nrows = 2, VERBOSE = TRUE)
print(my_df)
print(colnames(my_df))

“attribute_1”“next.attribute”“who.creates..these.horrible..column.nämes”

警告信息: 在 read.table(na.strings = c("\N", ""), sep = ";", dec = ".", colClasses > = list( : 并非所有在 'colClasses' 中命名的列都存在

所以这行得通,什么时候不应该? 当然,在调用 read.table.ffdf 时省略 check.names 的工作方式相同,所以有些地方会丢失。

2。查看 read.table.ffdf 的源代码

我去了 rdrr.io 网站 (read.table.ffdf-source-code) 查看源代码并试图了解,我做错了什么。简而言之,这就是我的文件发生的情况:

rt.args <- list(na.strings = c('\\N',''), sep= ';', dec= '.', colClasses = headclasses, check.names = FALSE , header = TRUE, nrows = 2)
rt.args$file <- path
asffdf_args <- list()

FUN <- 'read.table'
dat <- do.call(FUN, rt.args)
x <- do.call("as.ffdf", c(list(dat), asffdf_args))
#print(colnames(dat))
#print(colnames(x))

这会产生

“attribute_1”“下一个属性”“谁创建,这些可怕的)列&名称”

“attribute_1”“next.attribute”“who.creates..these.horrible..column.nämes”

好的,这就是问题所在。

我不知道要传递哪个 asffdf_args 并且由于我对 R 有点陌生,所以除了某种 check.names 等效项之外,我不确定要寻找什么。我已经通过

查看了 as.ffdf.data.frame 方法
getAnywhere(as.ffdf.data.frame)

但这并没有帮助我理解我应该输入什么。 那么,我怎样才能使 read.table.ffdf-与丑陋的列名一起工作?我必须通过哪个 'asffdf_args' 才能使 check.names = FALSE 在所述方法中工作?

我可以调整我的 switch 语句(大约 400 列),使用 check.names = TRUE 读取文件,在 read.table.ffdf 完成后,我可以将列名设置为所需的(因为我有以后使用更讨厌的名字)。但这对我来说是一种解决方法,根本不能满足我。

这是我在这里的第一个问题,所以请对我温柔一点,如果我忽略了一些重要的事情,请随时将我推向正确的方向。

提前感谢您的帮助。

【问题讨论】:

  • 我认为首先要解决的是colClasses应该是一个命名的字符向量而不是一个列表
  • 如果我将 headclasses 实例化为 vector(mode = 'character', length = 0),我仍然会得到同样的错误。
  • 我已经编辑了我的 sn-ps 以适应这种变化。

标签: r read.table


【解决方案1】:

事实上,您可能无法按照自己的意愿传递参数

as.ffdf.data.frame() 在最后一行调用ffdf()
ffdf 依次调用make.names 几次,不检查任何参数。

如果您编辑 ffdf(),并在函数的最后注释掉该行 vnam &lt;- make.names(vnam, unique = TRUE),那么as.ffdf.data.frame() 将能够保留您时髦的列名。
我不提供ffdf 的修改版本,因为函数超过300 行。

我测试了一个新函数ffdf_new,注入如下:

# save original version
orig <- ff::ffdf

# devtools::install_github("miraisolutions/godmode")
godmode:::assignAnywhere("ffdf", ffdf_new)

# simple test below
DF <- data.frame(
  'attribute_1' = 1:10,
  'next attribute' = 3:12,
  'who creates, these horrible) column&nämes' = 11:20,
  check.names = FALSE
)

as.ffdf.data.frame(DF)[["who creates, these horrible) column&nämes"]]
## ff (open) integer length=10 (10)
##  [1]  [2]  [3]  [4]  [5]  [6]  [7]  [8]  [9] [10] 
##   11   12   13   14   15   16   17   18   19   20 

# switch back
godmode:::assignAnywhere("ffdf", orig)

【讨论】:

  • 尽管在我看来这是一种解决方法,但这对我有很大帮助(但更糟糕的是什么?这个修复还是列名?;)非常感谢。
猜你喜欢
  • 2014-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多