使用R data.table fread时如何选择部分字符串匹配?

4

我想用fread函数仅读取符合条件的列。(在这种情况下,我想读取所有包含标签email的列。)假设您有一个名为tempdata.txt的文件,保存在您的工作目录中:

col1,col2,col3,email1,email2,col4,url1,url2,col5
1,2,3,4,5,6,7,8,9
9,8,7,6,5,4,3,2,1
x,x,x,me@me.com,you@you.com,y,y,y,y
a,a,a,a,a,a,http://google.com,http://stackoverflow.com,a

如果你知道列的名称,可以使用fread来加载子集:

test <- data.table::fread("tempdata.txt", select=c("email1","email2"))

> test
      email1      email2
1:         4           5
2:         6           5
3: me@me.com you@you.com
4:         a           a

可以使用字符串匹配进行选择吗?我试图模仿这种行为,但是要在fread命令中实现:

> all <- data.table::fread("tempdata.txt")
> all %>% select(contains("email"))
      email1      email2
1:         4           5
2:         6           5
3: me@me.com you@you.com
4:         a           a

感谢任何见解。

2个回答

4
我不确定 fread 没有这个功能(虽然文档中没有提到)。但是,一个相对便宜的方法是读取前一两行,获取列名,grep 它们,然后从那里继续进行。
library(data.table)
fwrite(data.table(a=1:2, email1=c('a','b'), snailmail=c('c','d'), email2=c('e','f')), "test.csv")
fread("test.csv", nrows=1)
#    a email1 snailmail email2
# 1: 1      a         c      e
cols <- colnames(fread("test.csv", nrows=0))
cols
# [1] "a"         "email1"    "snailmail" "email2"   
fread("test.csv", select = grep("^email", cols, value = TRUE))
#    email1 email2
# 1:      a      e
# 2:      b      f

3
是的,这是标准做法。你也可以使用nrows=0仅获取列名。 - MichaelChirico

3

当你的数据非常干净时,可以使用readLines来代替:

colnames = strsplit(readLines('test.csv', 1L), ',', fixed=TRUE)[[1L]]

使用fread会更快,因为它会带有一些开销:

microbenchmark::microbenchmark(
  times = 1e5,
  fread = fread("test.csv", nrows=0L),
  fread_optim = fread('test.csv', nrows=0L, sep=',', header=TRUE),
  read_csv = read.csv('test.csv', nrows=1L),
  strsplit = strsplit(readLines('test.csv', n=1L), ',', fixed=TRUE)[[1L]],
  scan = scan('test.csv', character(), nlines=1L, sep=',', quiet=TRUE)
)
# Unit: microseconds
#         expr     min      lq      mean   median       uq         max neval
#        fread 224.128 252.349 303.55132 270.4815 305.0580   62815.127 1e+05
#  fread_optim 224.410 253.128 378.10699 271.3815 306.3630 7451270.616 1e+05
#     read_csv 256.298 295.847 348.54183 316.1290 356.0520   46047.083 1e+05
#     strsplit  36.026  47.563  60.13347  55.3050  61.7490    6344.610 1e+05
#         scan  42.121  56.584  69.75281  63.5750  71.4535    6497.283 1e+05

当然要注意的是,所有时间单位都是微秒级别的,所以对于简单的用例来说这并不重要。

我说“当数据非常规整”时,因为fread在数据有一些杂质、或者你不知道sep的情况下,也应该能够(正常)工作。


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