orig_float = 232569 / 16000.0
14.5355625
blockquote>short_float = float("{:.2f}".format(orig_float))
14.54
blockquote>
fst
package Более поздняя опция для очень быстрого чтения и записи файлов данных - это пакет fst
. fst
создает файлы в двоичном формате.
Используйте write.fst(dat, "file.fst", compress=0)
, где compress
может перейти от 0 (без сжатия) до 100 (максимальное сжатие). Данные можно считать в R с помощью dat = read.fst("file.fst")
. На основе таймингов, перечисленных на веб-сайте package , он быстрее, чем feather
, data.table
и база R readRDS
и writeRDS
.
Сайт разработки пакета предупреждает, что формат данных fst
все еще развивается и что fst
, следовательно, еще не используется для долговременного хранения данных.
Другой вариант - использовать формат файла feather .
df <- as.data.frame(matrix(runif(256*65536), nrow = 256))
system.time(feather::write_feather(df, "df.feather"))
#> user system elapsed
#> 0.237 0.355 0.617
Feather - это формат двоичного файла, который очень эффективен для чтения и записи. Он предназначен для работы с несколькими языками: в настоящее время есть клиенты R и python, и клиент julia работает.
Для сравнения, вот как долго saveRDS
принимает:
system.time(saveRDS(df, "df.rds"))
#> user system elapsed
#> 17.363 0.307 17.856
Теперь это несколько несправедливое сравнение, потому что по умолчанию для saveRDS
используется сжатие данных, и здесь данные несжимаемы, потому что они полностью случайны. Сжатие сжимания делает saveRDS
значительно быстрее:
system.time(saveRDS(df, "df.rds", compress = FALSE))
#> user system elapsed
#> 0.181 0.247 0.473
И действительно, теперь он немного быстрее, чем перо. Так зачем использовать перо? Ну, это обычно быстрее, чем readRDS()
, и вы обычно записываете данные относительно немного раз по сравнению с количеством раз, которое вы читали.
system.time(readRDS("df.rds"))
#> user system elapsed
#> 0.198 0.090 0.287
system.time(feather::read_feather("df.feather"))
#> user system elapsed
#> 0.125 0.060 0.185
data.table::fwrite()
был предоставлен Отто Сейскари и доступен в версиях 1.9.8+. Мэтт сделал дополнительные улучшения сверху (включая параллелизацию) и написал статью об этом. Пожалуйста, сообщите о любых проблемах в трее .
Во-первых, вот сравнение того же размера, что и @chase выше (т. Е. Очень большое количество столбцов: 65 000 столбцов (! ) x 256 строк) вместе с fwrite
и write_feather
, так что мы имеем некоторую согласованность между машинами. Обратите внимание, что огромная разница compress=FALSE
делает в базе R.
# -----------------------------------------------------------------------------
# function | object type | output type | compress= | Runtime | File size |
# -----------------------------------------------------------------------------
# save | matrix | binary | FALSE | 0.3s | 134MB |
# save | data.frame | binary | FALSE | 0.4s | 135MB |
# feather | data.frame | binary | FALSE | 0.4s | 139MB |
# fwrite | data.table | csv | FALSE | 1.0s | 302MB |
# save | matrix | binary | TRUE | 17.9s | 89MB |
# save | data.frame | binary | TRUE | 18.1s | 89MB |
# write.csv | matrix | csv | FALSE | 21.7s | 302MB |
# write.csv | data.frame | csv | FALSE | 121.3s | 302MB |
Обратите внимание, что fwrite()
работает параллельно. Показанное здесь время представлено на 13-дюймовом MacBook Pro с 2 ядрами и 1 потоком / ядром (+2 виртуальных потока через гиперпоточность), 512 ГБ SSD, кеш второго уровня 256 КБ / кэш и 4 МБ кэша L4. В зависимости от вашей спецификации системы, YMMV.
Я также пересматриваю тесты относительно более вероятных (и больших) данных:
library(data.table)
NN <- 5e6 # at this number of rows, the .csv output is ~800Mb on my machine
set.seed(51423)
DT <- data.table(
str1 = sample(sprintf("%010d",1:NN)), #ID field 1
str2 = sample(sprintf("%09d",1:NN)), #ID field 2
# varying length string field--think names/addresses, etc.
str3 = replicate(NN,paste0(sample(LETTERS,sample(10:30,1),T), collapse="")),
# factor-like string field with 50 "levels"
str4 = sprintf("%05d",sample(sample(1e5,50),NN,T)),
# factor-like string field with 17 levels, varying length
str5 = sample(replicate(17,paste0(sample(LETTERS, sample(15:25,1),T),
collapse="")),NN,T),
# lognormally distributed numeric
num1 = round(exp(rnorm(NN,mean=6.5,sd=1.5)),2),
# 3 binary strings
str6 = sample(c("Y","N"),NN,T),
str7 = sample(c("M","F"),NN,T),
str8 = sample(c("B","W"),NN,T),
# right-skewed (integer type)
int1 = as.integer(ceiling(rexp(NN))),
num2 = round(exp(rnorm(NN,mean=6,sd=1.5)),2),
# lognormal numeric that can be positive or negative
num3 = (-1)^sample(2,NN,T)*round(exp(rnorm(NN,mean=6,sd=1.5)),2))
# -------------------------------------------------------------------------------
# function | object | out | other args | Runtime | File size |
# -------------------------------------------------------------------------------
# fwrite | data.table | csv | quote = FALSE | 1.7s | 523.2MB |
# fwrite | data.frame | csv | quote = FALSE | 1.7s | 523.2MB |
# feather | data.frame | bin | no compression | 3.3s | 635.3MB |
# save | data.frame | bin | compress = FALSE | 12.0s | 795.3MB |
# write.csv | data.frame | csv | row.names = FALSE | 28.7s | 493.7MB |
# save | data.frame | bin | compress = TRUE | 48.1s | 190.3MB |
# -------------------------------------------------------------------------------
Таким образом, fwrite
~ 2x быстрее, чем feather
в этом тесте. Это было выполнено на той же машине, что указано выше, когда fwrite
работает параллельно на 2 ядрах.
feather
также выглядит довольно быстрым двоичным форматом, но пока нет сжатия.
Вот попытка показать, как fwrite
сравнивается по шкале:
NB: эталон был обновлен путем запуска базы R save()
с compress = FALSE
(поскольку перо также не является сжатый).
Таким образом, fwrite
является самым быстрым из всех этих данных (работает на 2 ядрах) плюс создает .csv
который можно легко просмотреть, проверить и передать на grep
, sed
и т. д.
Код для воспроизведения:
require(data.table)
require(microbenchmark)
require(feather)
ns <- as.integer(10^seq(2, 6, length.out = 25))
DTn <- function(nn)
data.table(
str1 = sample(sprintf("%010d",1:nn)),
str2 = sample(sprintf("%09d",1:nn)),
str3 = replicate(nn,paste0(sample(LETTERS,sample(10:30,1),T), collapse="")),
str4 = sprintf("%05d",sample(sample(1e5,50),nn,T)),
str5 = sample(replicate(17,paste0(sample(LETTERS, sample(15:25,1),T), collapse="")),nn,T),
num1 = round(exp(rnorm(nn,mean=6.5,sd=1.5)),2),
str6 = sample(c("Y","N"),nn,T),
str7 = sample(c("M","F"),nn,T),
str8 = sample(c("B","W"),nn,T),
int1 = as.integer(ceiling(rexp(nn))),
num2 = round(exp(rnorm(nn,mean=6,sd=1.5)),2),
num3 = (-1)^sample(2,nn,T)*round(exp(rnorm(nn,mean=6,sd=1.5)),2))
count <- data.table(n = ns,
c = c(rep(1000, 12),
rep(100, 6),
rep(10, 7)))
mbs <- lapply(ns, function(nn){
print(nn)
set.seed(51423)
DT <- DTn(nn)
microbenchmark(times = count[n==nn,c],
write.csv=write.csv(DT, "writecsv.csv", quote=FALSE, row.names=FALSE),
save=save(DT, file = "save.RData", compress=FALSE),
fwrite=fwrite(DT, "fwrite_turbo.csv", quote=FALSE, sep=","),
feather=write_feather(DT, "feather.feather"))})
png("microbenchmark.png", height=600, width=600)
par(las=2, oma = c(1, 0, 0, 0))
matplot(ns, t(sapply(mbs, function(x) {
y <- summary(x)[,"median"]
y/y[3]})),
main = "Relative Speed of fwrite (turbo) vs. rest",
xlab = "", ylab = "Time Relative to fwrite (turbo)",
type = "l", lty = 1, lwd = 2,
col = c("red", "blue", "black", "magenta"), xaxt = "n",
ylim=c(0,25), xlim=c(0, max(ns)))
axis(1, at = ns, labels = prettyNum(ns, ","))
mtext("# Rows", side = 1, las = 1, line = 5)
legend("right", lty = 1, lwd = 3,
legend = c("write.csv", "save", "feather"),
col = c("red", "blue", "magenta"))
dev.off()
Вы также можете попробовать read_rds 'readr' (по сравнению с data.table :: fread) и write_rds (по сравнению с data.table :: fwrite).
Вот простой пример в моем наборе данных (1133 строки и 429499 столбцов):
fwrite(rankp2,file="rankp2_429499.txt",col.names=T,row.names=F,quote = F,sep="\t")
write_rds(rankp2,"rankp2_429499.rds")
system.time(fread("rankp2_429499.txt",sep="\t",header=T,fill = TRUE))
user system elapsed
42.391 0.526 42.949
system.time(read_rds("rankp2_429499.rds"))
user system elapsed
2.157 0.388 2.547
Надеюсь, что это поможет.