R data.table fread select 与部分字符串匹配?
R data.table fread select with a partial string match?
我想使用 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://whosebug.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
是否也可以 select 使用字符串匹配?我试图模仿这种行为,但在 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
感谢您的任何见解。
我不知道 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
当您的数据非常干净时,另一种方法是使用 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
当然请注意,一切都以微秒为单位,因此对于简单的用例来说,这无关紧要。
我说 "when your data is very clean" 因为 fread
也可以(应该)在你的数据有点脏的情况下工作,或者如果你事先不知道 sep
,等等
我想使用 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://whosebug.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
是否也可以 select 使用字符串匹配?我试图模仿这种行为,但在 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
感谢您的任何见解。
我不知道 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
当您的数据非常干净时,另一种方法是使用 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
当然请注意,一切都以微秒为单位,因此对于简单的用例来说,这无关紧要。
我说 "when your data is very clean" 因为 fread
也可以(应该)在你的数据有点脏的情况下工作,或者如果你事先不知道 sep
,等等