【问题标题】:R data.table fread select with a partial string match?R data.table fread select与部分字符串匹配?
【发布时间】:2020-09-24 04:19:59
【问题描述】:

我想使用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

感谢您的任何见解。

【问题讨论】:

    标签: r select data.table fread


    【解决方案1】:

    当您的数据非常干净时,另一种方法是使用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 等等。

    【讨论】:

      【解决方案2】:

      我不知道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
      

      【讨论】:

      • 是的,这是规范的方法,您也可以使用nrows=0 仅获取列名
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 2016-10-18
      • 1970-01-01
      相关资源
      最近更新 更多