Lecture rapide de très grands tableaux en tant que cadres de données

504

J'ai de très grandes tables (30 millions de lignes) que je voudrais charger car les trames de données dans R. read.table()ont beaucoup de fonctionnalités pratiques, mais il semble qu'il y ait beaucoup de logique dans l'implémentation qui ralentirait les choses. Dans mon cas, je suppose que je connais les types de colonnes à l'avance, le tableau ne contient aucun en-tête de colonne ou nom de ligne et n'a pas de caractères pathologiques dont je dois m'inquiéter.

Je sais que la lecture dans un tableau sous forme de liste scan()peut être assez rapide, par exemple:

datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))

Mais certaines de mes tentatives pour convertir cela en une trame de données semblent réduire les performances de ce qui précède d'un facteur 6:

df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))

Existe-t-il une meilleure façon de le faire? Ou peut-être une approche complètement différente du problème?

eytan
la source

Réponses:

426

Une mise à jour, plusieurs années plus tard

Cette réponse est ancienne et R est passé à autre chose. Ajuster read.tablepour courir un peu plus vite n'a que peu d'avantages précieux. Vos options sont:

  1. Utilisation à vroompartir du package tidyverse vroompour importer des données depuis des fichiers délimités par csv / tab directement dans un tibble R.

  2. Utiliser freadin data.tablepour importer des données à partir de fichiers délimités par csv / tab directement dans R. Voir la réponse de mnel .

  3. Utilisation read_tabledans readr(sur CRAN à partir d'avril 2015). Cela fonctionne comme freadci-dessus. Le fichier Lisezmoi du lien explique la différence entre les deux fonctions ( readrprétend actuellement être "1,5-2x plus lent" que data.table::fread).

  4. read.csv.rawfrom iotoolsfournit une troisième option pour lire rapidement les fichiers CSV.

  5. Essayer de stocker autant de données que possible dans des bases de données plutôt que dans des fichiers plats. (En plus d'être un meilleur support de stockage permanent, les données sont transmises vers et depuis R dans un format binaire, ce qui est plus rapide.) read.csv.sqlDans le sqldfpackage, comme décrit dans la réponse de JD Long , importe les données dans une base de données SQLite temporaire puis les lit dans R. Voir aussi: le RODBCpaquet et l'inverse dépend de la section de la page du DBIpaquet . MonetDB.Rvous donne un type de données qui prétend être une trame de données mais qui est vraiment un MonetDB en dessous, augmentant les performances. Importez des données avec sa monetdb.read.csvfonction. dplyrvous permet de travailler directement avec des données stockées dans plusieurs types de base de données.

  6. Le stockage de données au format binaire peut également être utile pour améliorer les performances. Utilisez saveRDS/ readRDS(voir ci-dessous), les packages h5ou rhdf5pour le format HDF5, ou write_fst/ à read_fstpartir du fstpackage.


La réponse originale

Il y a quelques choses simples à essayer, que vous utilisiez read.table ou scan.

  1. Set nrows= le nombre d'enregistrements dans vos données ( nmaxen scan).

  2. Assurez-vous que comment.char=""pour désactiver l'interprétation des commentaires.

  3. Définissez explicitement les classes de chaque colonne à l'aide de colClassesdans read.table.

  4. Le réglage multi.line=FALSEpeut également améliorer les performances de l'analyse.

Si aucune de ces choses ne fonctionne, utilisez l'un des packages de profilage pour déterminer quelles lignes ralentissent les choses. Vous pouvez peut-être rédiger une version réduite de read.tablesur la base des résultats.

L'autre alternative consiste à filtrer vos données avant de les lire dans R.

Ou, si le problème est que vous devez le lire régulièrement, utilisez ces méthodes pour lire les données une fois, puis enregistrez le bloc de données en tant qu'objet binaire avec save saveRDS, puis la prochaine fois, vous pourrez le récupérer plus rapidement avec load readRDS.

Richie Cotton
la source
4
Merci pour les conseils Richie. J'ai fait quelques tests, et il semble que les gains de performances avec l'utilisation des options nrow et colClasses pour read.table soient assez modestes. Par exemple, la lecture d'un tableau de lignes de ~ 7 M prend 78 secondes sans les options et 67 secondes avec les options. (note: la table a 1 colonne de caractères, 4 colonnes entières, et j'ai lu en utilisant comment.char = '' et stringsAsFactors = FALSE). Utiliser save () et load () lorsque c'est possible est une excellente astuce - une fois stockée avec save (), cette même table ne prend que 12s à charger.
eytan
2
Le package "feather" a un nouveau format binaire qui joue bien avec les trames de données pandas de Python
rsoren
4
Je pense que vous devez peut-être mettre à jour votre message en ce qui concerne le package feather. Pour la lecture des données featherest beaucoup plus rapide que fread. Par exemple, sur un ensemble de données de 4 Go que je viens de charger read_featherétait environ 4,5 fois plus rapide que fread. Pour l'enregistrement des données fwriteest encore plus rapide. blog.dominodatalab.com/the-r-data-io-shootout
Z boson
2
Mais les tailles de fichier sont beaucoup plus grandes pour les plumes qu'avec RDS. Je ne pense pas qu'il supporte la compression. Le fichier RDS est de 216 Mo et le fichier de plumes est de 4 Go. Il featherest donc plus rapide pour la lecture, mais il utilise beaucoup plus d'espace de stockage.
Z boson du
@Zboson Si vous avez besoin de stocker une trame de données dans un fichier accessible à la fois depuis R et Python, featherc'est une bonne option. Si vous ne souhaitez que lire vos données en R, il rdsest préférable.
Richie Cotton
279

Voici un exemple qui utilise freadde data.table1.8.7

Les exemples viennent de la page d'aide de fread, avec les timings sur mon windows XP Core 2 duo E8400.

library(data.table)
# Demo speedup
n=1e6
DT = data.table( a=sample(1:1000,n,replace=TRUE),
                 b=sample(1:1000,n,replace=TRUE),
                 c=rnorm(n),
                 d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE),
                 e=rnorm(n),
                 f=sample(1:1000,n,replace=TRUE) )
DT[2,b:=NA_integer_]
DT[4,c:=NA_real_]
DT[3,d:=NA_character_]
DT[5,d:=""]
DT[2,e:=+Inf]
DT[3,e:=-Inf]

table de lecture standard

write.table(DT,"test.csv",sep=",",row.names=FALSE,quote=FALSE)
cat("File size (MB):",round(file.info("test.csv")$size/1024^2),"\n")    
## File size (MB): 51 

system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
##    user  system elapsed 
##   24.71    0.15   25.42
# second run will be faster
system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
##    user  system elapsed 
##   17.85    0.07   17.98

table de lecture optimisée

system.time(DF2 <- read.table("test.csv",header=TRUE,sep=",",quote="",  
                          stringsAsFactors=FALSE,comment.char="",nrows=n,                   
                          colClasses=c("integer","integer","numeric",                        
                                       "character","numeric","integer")))


##    user  system elapsed 
##   10.20    0.03   10.32

effrayer

require(data.table)
system.time(DT <- fread("test.csv"))                                  
 ##    user  system elapsed 
##    3.12    0.01    3.22

sqldf

require(sqldf)

system.time(SQLDF <- read.csv.sql("test.csv",dbname=NULL))             

##    user  system elapsed 
##   12.49    0.09   12.69

# sqldf as on SO

f <- file("test.csv")
system.time(SQLf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))

##    user  system elapsed 
##   10.21    0.47   10.73

ff / ffdf

 require(ff)

 system.time(FFDF <- read.csv.ffdf(file="test.csv",nrows=n))   
 ##    user  system elapsed 
 ##   10.85    0.10   10.99

En résumé:

##    user  system elapsed  Method
##   24.71    0.15   25.42  read.csv (first time)
##   17.85    0.07   17.98  read.csv (second time)
##   10.20    0.03   10.32  Optimized read.table
##    3.12    0.01    3.22  fread
##   12.49    0.09   12.69  sqldf
##   10.21    0.47   10.73  sqldf on SO
##   10.85    0.10   10.99  ffdf
mnel
la source
43
Excellente réponse, et l'analyse comparative tient dans d'autres contextes. Il suffit de lire un fichier de 4 Go en moins d'une minute avec fread. J'avais essayé de le lire avec les fonctions de base R et cela a pris environ 15 heures.
Ari B. Friedman
1
mon benchmark suggère des avantages de vitesse encore plus grands pour read.csv dans data.table. notez que data.table n'est pas du R standard, mais (malheureusement) "juste" bien partagé par ses créateurs sur CRAN. il n'est même pas jugé suffisamment standard pour constituer la liste de packages R commune, et encore moins être considéré comme un remplacement pour les trames de données. il présente de nombreux avantages, mais aussi des aspects très contre-intuitifs. vous souhaiterez peut-être utiliser as.data.frame (fread.csv ("test.csv")) avec le package pour revenir dans le monde des trames de données R standard.
ivo Welch
3
@mnel pourriez-vous réexécuter le benchmark et l'inclure readr?
jangorecki
2
Deuxième @jangorecki. De plus, étant donné qu'il y freada maintenant de vrais concurrents, il pourrait être utile d'ajouter des repères pour une freadutilisation optimisée - en spécifiant colClasses, etc.
MichaelChirico
1
@jangorecji @ MichaelChirico, le code donné est entièrement reproductible, il est donc simple de simuler la lecture ... la réexécution du code, sur ma machine, le temps écoulé est deux fois plus rapide sinon plus pour la plupart des résultats, même si je l'exécute sur un réseau (et versions bien mises à jour car il y a un certain temps maintenant ... la peur pour la solution la plus rapide montrée ici est à 2s de mon côté pour comparaison (première fois à 8,69s) pour une raison plus lente)
R. Prost
249

Je n'ai pas vu cette question au départ et posé une question similaire quelques jours plus tard. Je vais reprendre ma question précédente, mais j'ai pensé ajouter une réponse ici pour expliquer comment je faisais sqldf()cela.

Il y a eu peu de discussions sur la meilleure façon d'importer 2 Go ou plus de données texte dans un bloc de données R. Hier, j'ai écrit un article de blog sur l'utilisation sqldf()de l'importation de données dans SQLite en tant que zone de transit, puis sur l'aspiration de SQLite dans R. Cela fonctionne très bien pour moi. J'ai pu extraire 2 Go (3 colonnes, lignes de 40 mm) de données en moins de 5 minutes. En revanche, la read.csvcommande a fonctionné toute la nuit et n'a jamais abouti.

Voici mon code de test:

Configurez les données de test:

bigdf <- data.frame(dim=sample(letters, replace=T, 4e7), fact1=rnorm(4e7), fact2=rnorm(4e7, 20, 50))
write.csv(bigdf, 'bigdf.csv', quote = F)

J'ai redémarré R avant d'exécuter la routine d'importation suivante:

library(sqldf)
f <- file("bigdf.csv")
system.time(bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))

J'ai laissé la ligne suivante fonctionner toute la nuit mais elle ne s'est jamais terminée:

system.time(big.df <- read.csv('bigdf.csv'))
JD Long
la source
1
Salut. Comment l'utiliserez-vous comme entrée pour d'autres packages tels que zoo, conçus pour être utilisés avec toutes les données simultanément?
skan
@skan l'objet final est un bloc de données. Vous devez donc le convertir en objet zoo afin de l'utiliser avec zoo. Regardez les exemples dans les documents du zoo pour des illustrations.
JD Long
@JD Long. Salut, le problème est que lorsque vous le convertissez en objet de zoo, il essaie de l'adapter à la mémoire. S'il est trop grand, il génère une erreur. Et si le résultat de l'objet zoo (par exemple une agrégation de deux séries) l'est également, il devrait également être un objet sql ou ff.
skan
Je ne sais pas ce qui ne va pas avec sqldf. J'ai créé un simple fichier de 1 Go sur le disque (avec 2 colonnes numériques) et utilisé DTSQL <- read.csv.sql ("f2.txt", dbname = tempfile ()) et il essaie de charger toutes les données en mémoire. Demain, je vais essayer ff et revoscaler à la place.
skan
1
@ quel m est mille donc mm est mille mille ou million. J'aurais probablement dû le mettre en majuscule comme MM. Mais je trouve que n'importe quel million d'abréviations peut être déroutant pour quelqu'un si vous avez un public suffisamment diversifié. Dans ma tentative d'être trop verbeux, je suis désolé de l'avoir rendu plus déroutant! accountingcoach.com/blog/what-does-m-and-mm-stand-for
JD Long
73

Étrangement, personne n'a répondu à la partie inférieure de la question pendant des années, même s'il s'agit d'une question importante - ce data.framesont simplement des listes avec les bons attributs, donc si vous avez de grandes données, vous ne voulez pas les utiliser as.data.frameou similaires pour une liste. Il est beaucoup plus rapide de simplement "transformer" une liste en un bloc de données sur place:

attr(df, "row.names") <- .set_row_names(length(df[[1]]))
class(df) <- "data.frame"

Cela ne fait aucune copie des données, c'est donc immédiat (contrairement à toutes les autres méthodes). Il suppose que vous avez déjà défini names()la liste en conséquence.

[Quant au chargement de grandes données dans R - personnellement, je les vide par colonne dans des fichiers binaires et les utilise readBin()- qui est de loin la méthode la plus rapide (autre que le mmapping) et n'est limitée que par la vitesse du disque. L'analyse des fichiers ASCII est intrinsèquement lente (même en C) par rapport aux données binaires.]

Simon Urbanek
la source
6
L'utilisation tracmemsuggère cela attr<-et class<-faites des copies en interne. bit::setattrou data.table::setattrpas.
mnel
6
Vous avez peut-être utilisé la mauvaise commande? Il n'y a pas de copie si vous utilisez df=scan(...); names(df)=...; attr...; class...- voir tracemem()(testé dans R 2.15.2)
Simon Urbanek
3
Pouvez-vous élaborer sur la façon de vider les grandes données par colonne dans des fichiers binaires?
dabsingh
32

Cela a déjà été demandé sur R-Help , donc cela vaut la peine d'être examiné.

Une suggestion était d'utiliser readChar()puis de manipuler les chaînes sur le résultat avec strsplit()et substr(). Vous pouvez voir que la logique impliquée dans readChar est bien inférieure à read.table.

Je ne sais pas si la mémoire est un problème ici, mais vous voudrez peut-être également jeter un œil au package HadoopStreaming . Cela utilise Hadoop , qui est un cadre MapReduce conçu pour traiter des ensembles de données volumineux. Pour cela, vous utiliseriez la fonction hsTableReader. Ceci est un exemple (mais il a une courbe d'apprentissage pour apprendre Hadoop):

str <- "key1\t3.9\nkey1\t8.9\nkey1\t1.2\nkey1\t3.9\nkey1\t8.9\nkey1\t1.2\nkey2\t9.9\nkey2\"
cat(str)
cols = list(key='',val=0)
con <- textConnection(str, open = "r")
hsTableReader(con,cols,chunkSize=6,FUN=print,ignoreKey=TRUE)
close(con)

L'idée de base ici est de diviser l'importation de données en morceaux. Vous pouvez même aller jusqu'à utiliser l'un des frameworks parallèles (par exemple snow) et exécuter l'importation de données en parallèle en segmentant le fichier, mais très probablement pour les grands ensembles de données qui ne vous aideront pas car vous rencontrerez des contraintes de mémoire, c'est pourquoi map-Reduce est une meilleure approche.

Shane
la source
Je viens de faire un test rapide et readChar semble être beaucoup plus rapide que même readLines pour une raison inexplicable. Cependant, il est toujours aussi lent que le péché par rapport à un simple test C. À la tâche simple de lire 100 mégaoctets, R est environ 5 à 10 fois plus lent que C
Jonathan Chang
1
Je ne comprends pas votre point. Le but de Hadoop est de gérer de très grandes données, ce qui était la question.
Shane
1
Malgré son nom, hsTableReader n'a rien à voir avec Hadoop en soi, c'est pour traiter de grandes données en morceaux. Il lit depuis con, un bloc de lignes à la fois, et transmet chaque bloc en tant que data.frame à FUN pour le traitement. Avec ignoreKey = FALSE, il effectue un regroupement supplémentaire par clé (l'entrée dans la première colonne), ce qui est pertinent pour les approches Map / Reduce.
DavidR
Salut. Comment utiliseriez-vous ces données Hadoop comme entrée pour d'autres packages tels que zoo, conçus pour être utilisés avec toutes les données simultanément?
skan
10

Une alternative consiste à utiliser le vroompackage. Maintenant sur CRAN. vroomne charge pas l'intégralité du fichier, il indexe l'emplacement de chaque enregistrement et est lu plus tard lorsque vous l'utilisez.

Ne payez que ce que vous utilisez.

Voir Introduction à vroom , Premiers pas avec vroom et les références de vroom .

L'aperçu de base est que la lecture initiale d'un fichier volumineux sera beaucoup plus rapide et que les modifications ultérieures des données peuvent être légèrement plus lentes. Selon votre utilisation, cela pourrait donc être la meilleure option.

Voir un exemple simplifié des références Vroom ci-dessous, les éléments clés à voir sont les temps de lecture super rapides, mais les opérations légèrement semées comme l'agrégat, etc.

package                 read    print   sample   filter  aggregate   total
read.delim              1m      21.5s   1ms      315ms   764ms       1m 22.6s
readr                   33.1s   90ms    2ms      202ms   825ms       34.2s
data.table              15.7s   13ms    1ms      129ms   394ms       16.3s
vroom (altrep) dplyr    1.7s    89ms    1.7s     1.3s    1.9s        6.7s
Hector Haffenden
la source
5

Quelques points supplémentaires mineurs qui méritent d'être mentionnés. Si vous avez un très gros fichier, vous pouvez calculer à la volée le nombre de lignes (si aucun en-tête) en utilisant (où bedGraphest le nom de votre fichier dans votre répertoire de travail):

>numRow=as.integer(system(paste("wc -l", bedGraph, "| sed 's/[^0-9.]*\\([0-9.]*\\).*/\\1/'"), intern=T))

Vous pouvez ensuite l'utiliser soit dans read.csv, read.table...

>system.time((BG=read.table(bedGraph, nrows=numRow, col.names=c('chr', 'start', 'end', 'score'),colClasses=c('character', rep('integer',3)))))
   user  system elapsed 
 25.877   0.887  26.752 
>object.size(BG)
203949432 bytes
Stephen Henderson
la source
4

Souvent, je pense que c'est juste une bonne pratique de garder de plus grandes bases de données à l'intérieur d'une base de données (par exemple Postgres). Je n'utilise rien de trop grand que (nrow * ncol) ncell = 10M, ce qui est assez petit; mais je trouve souvent que je veux que R crée et conserve des graphiques gourmands en mémoire uniquement pendant que je recherche à partir de plusieurs bases de données. À l'avenir des ordinateurs portables de 32 Go, certains de ces types de problèmes de mémoire disparaîtront. Mais l'attrait d'utiliser une base de données pour conserver les données, puis d'utiliser la mémoire de R pour les résultats de requête et les graphiques résultants peut toujours être utile. Quelques avantages:

(1) Les données restent chargées dans votre base de données. Vous vous reconnectez simplement dans pgadmin aux bases de données que vous souhaitez lorsque vous rallumez votre ordinateur portable.

(2) Il est vrai que R peut effectuer des opérations statistiques et graphiques beaucoup plus astucieuses que SQL. Mais je pense que SQL est mieux conçu pour interroger de grandes quantités de données que R.

# Looking at Voter/Registrant Age by Decade

library(RPostgreSQL);library(lattice)

con <- dbConnect(PostgreSQL(), user= "postgres", password="password",
                 port="2345", host="localhost", dbname="WC2014_08_01_2014")

Decade_BD_1980_42 <- dbGetQuery(con,"Select PrecinctID,Count(PrecinctID),extract(DECADE from Birthdate) from voterdb where extract(DECADE from Birthdate)::numeric > 198 and PrecinctID in (Select * from LD42) Group By PrecinctID,date_part Order by Count DESC;")

Decade_RD_1980_42 <- dbGetQuery(con,"Select PrecinctID,Count(PrecinctID),extract(DECADE from RegistrationDate) from voterdb where extract(DECADE from RegistrationDate)::numeric > 198 and PrecinctID in (Select * from LD42) Group By PrecinctID,date_part Order by Count DESC;")

with(Decade_BD_1980_42,(barchart(~count | as.factor(precinctid))));
mtext("42LD Birthdays later than 1980 by Precinct",side=1,line=0)

with(Decade_RD_1980_42,(barchart(~count | as.factor(precinctid))));
mtext("42LD Registration Dates later than 1980 by Precinct",side=1,line=0)
rferrisx
la source
3

Je lis les données très rapidement en utilisant le nouveau arrowpackage. Il semble être à un stade assez précoce.

Plus précisément, j'utilise le format colonnaire parquet . Cela se reconvertit en un data.framedans R, mais vous pouvez obtenir des accélérations encore plus profondes si vous ne le faites pas. Ce format est pratique car il peut également être utilisé à partir de Python.

Mon cas d'utilisation principal pour cela est sur un serveur RShiny assez restreint. Pour ces raisons, je préfère garder les données attachées aux applications (c'est-à-dire en dehors de SQL), et donc nécessiter une petite taille de fichier ainsi qu'une vitesse.

Cet article lié fournit une analyse comparative et un bon aperçu. J'ai cité quelques points intéressants ci-dessous.

https://ursalabs.org/blog/2019-10-columnar-perf/

Taille du fichier

Autrement dit, le fichier Parquet est deux fois moins volumineux que le CSV compressé. L'une des raisons pour lesquelles le fichier Parquet est si petit est à cause de l'encodage du dictionnaire (également appelé «compression du dictionnaire»). La compression de dictionnaire peut produire une compression sensiblement meilleure que l'utilisation d'un compresseur d'octets à usage général comme LZ4 ou ZSTD (qui sont utilisés au format FST). Parquet a été conçu pour produire de très petits fichiers faciles à lire.

Vitesse de lecture

Lors du contrôle par type de sortie (par exemple en comparant toutes les sorties R data.frame entre elles), nous voyons que les performances de Parquet, Feather et FST se situent dans une marge relativement petite les unes des autres. Il en va de même pour les sorties pandas.DataFrame. data.table :: fread est incroyablement compétitif avec la taille de fichier de 1,5 Go mais est en retard sur les autres sur le CSV de 2,5 Go.


Test indépendant

J'ai effectué une analyse comparative indépendante sur un ensemble de données simulées de 1 000 000 de lignes. Fondamentalement, j'ai mélangé un tas de choses pour tenter de contester la compression. J'ai également ajouté un court champ de texte de mots aléatoires et deux facteurs simulés.

Les données

library(dplyr)
library(tibble)
library(OpenRepGrid)

n <- 1000000

set.seed(1234)
some_levels1 <- sapply(1:10, function(x) paste(LETTERS[sample(1:26, size = sample(3:8, 1), replace = TRUE)], collapse = ""))
some_levels2 <- sapply(1:65, function(x) paste(LETTERS[sample(1:26, size = sample(5:16, 1), replace = TRUE)], collapse = ""))


test_data <- mtcars %>%
  rownames_to_column() %>%
  sample_n(n, replace = TRUE) %>%
  mutate_all(~ sample(., length(.))) %>%
  mutate(factor1 = sample(some_levels1, n, replace = TRUE),
         factor2 = sample(some_levels2, n, replace = TRUE),
         text = randomSentences(n, sample(3:8, n, replace = TRUE))
         )

Lire et écrire

L'écriture des données est facile.

library(arrow)

write_parquet(test_data , "test_data.parquet")

# you can also mess with the compression
write_parquet(test_data, "test_data2.parquet", compress = "gzip", compression_level = 9)

La lecture des données est également facile.

read_parquet("test_data.parquet")

# this option will result in lightning fast reads, but in a different format.
read_parquet("test_data2.parquet", as_data_frame = FALSE)

J'ai testé la lecture de ces données par rapport à quelques-unes des options concurrentes et j'ai obtenu des résultats légèrement différents de ceux de l'article ci-dessus, ce qui est attendu.

analyse comparative

Ce fichier est loin d'être aussi volumineux que l'article de référence, alors c'est peut-être la différence.

Les tests

  • rds: test_data.rds (20,3 Mo)
  • parquet2_native: (14,9 Mo avec une compression plus élevée et as_data_frame = FALSE)
  • parquet2: test_data2.parquet (14,9 Mo avec une compression plus élevée)
  • parquet: test_data.parquet (40,7 Mo)
  • fst2: test_data2.fst (27,9 Mo avec une compression plus élevée)
  • fst: test_data.fst (76,8 Mo)
  • fread2: test_data.csv.gz (23,6 Mo)
  • fread: test_data.csv (98,7 Mo)
  • feather_arrow: test_data.feather (157,2 Mo lu avec arrow)
  • feather: test_data.feather (157,2 Mo lu avec feather)

Observations

Pour ce fichier particulier, freadest en fait très rapide. J'aime la petite taille du fichier du parquet2test hautement compressé . Je peux investir du temps pour travailler avec le format de données natif plutôt que data.framesi j'ai vraiment besoin d'accélérer.

Voici fstégalement un excellent choix. J'utiliserais soit le fstformat hautement compressé , soit le format hautement compressé, parquetselon que j'aurais besoin d'un compromis entre la vitesse ou la taille du fichier.

Adam
la source
0

Au lieu de la table de lecture conventionnelle, je pense que la peur est une fonction plus rapide. La spécification d'attributs supplémentaires, comme sélectionner uniquement les colonnes requises, la spécification des colclasses et de la chaîne comme facteurs réduira le temps nécessaire pour importer le fichier.

data_frame <- fread("filename.csv",sep=",",header=FALSE,stringsAsFactors=FALSE,select=c(1,4,5,6,7),colClasses=c("as.numeric","as.character","as.numeric","as.Date","as.Factor"))
Aayush Agrawal
la source
0

J'ai tout essayé ci-dessus et [readr] [1] a fait le meilleur travail. Je n'ai que 8 Go de RAM

Boucle pour 20 fichiers, 5 Go chacun, 7 colonnes:

read_fwf(arquivos[i],col_types = "ccccccc",fwf_cols(cnpj = c(4,17), nome = c(19,168), cpf = c(169,183), fantasia = c(169,223), sit.cadastral = c(224,225), dt.sitcadastral = c(226,233), cnae = c(376,382)))
Brun Ijbh
la source