0
votes

Filtrer les fichiers CSV pour une valeur spécifique avant d'importer

J'ai un dossier avec des milliers de fichiers CSV délimités par des virgules, totalisant des dizaines de GB. Chaque fichier contient de nombreux enregistrements, que je souhaite séparer et traiter séparément en fonction de la valeur dans le premier champ (par exemple, AA, BB, CC, etc.).

Actuellement, j'importe tous les fichiers dans un fichier de données puis sous-téléposez dans R dans des fichiers de données plus petits et individuels. Le problème est que cela est très intensif de mémoire - je voudrais filtrer la première colonne pendant le processus d'importation, et non une fois que toutes les données sont en mémoire de mémoire. P>

Ceci est mon code actuel: P>

setwd("E:/Data/")
files <- list.files(path = "E:/Data/",pattern = "*.csv")
temp <- lapply(files, fread, sep=",", fill=TRUE, integer64="numeric",header=FALSE)
DF <- rbindlist(temp)
DFaa <- subset(DF, V1 =="aa")

r

1 commentaires

Vous devriez faire référence au paquet qui contient "Fread" car ce n'est pas une fonction de base.


4 Réponses :


0
votes

Cela pourrait vous aider, mais vous devez développer la fonction:

#Function
myload <- function(x) 
{
  y <- fread(x, sep=",", fill=TRUE, integer64="numeric",header=FALSE)
  y <- subset(y, V1 =="aa")
  return(y)
}
#Apply
temp <- lapply(files, myload)


1 commentaires

Cela n'aide pas, car vous avez toujours lu tout le contenu.



0
votes
setwd("E:/Data/")
files <- list.files(path = "E:/Data/",pattern = "*.csv")
temp <- lapply(files, function(x) subset(fread(x, sep=",", fill=TRUE, integer64="numeric",header=FALSE), V1=="aa"))
DF <- rbindlist(temp)
Untested, but this will probably work - replace your function call with an anonymous function.

3 commentaires

Merci, c'est génial.


Cela «aidera» à ce que la mémoire est libérée après le traitement de chaque fichier. Si toutefois un seul fichier souffle de RAM, cela ne vous aidera pas.


D'accord, mais c'était le problème présenté - chaque dossier est assez petit, c'est juste que tous combinés sont trop gros. Il est également vrai que si la liste filtrée combinée est trop grosse, cela ne vous aidera pas non plus, mais il a été supposé que ce n'est pas le cas, étant donné le problème présenté.



2
votes

1) read.csv.sql strong> Cela lira un fichier directement dans une base de données SQLite définie temporairement (que ce soit pour vous), puis lisez uniquement le aa code> Les enregistrements dans R. Le reste du fichier ne sera pas lu dans R à tout moment. La table sera ensuite supprimée de la base de données.

fichier code> est une chaîne de caractères contenant le nom de fichier (ou chemin de chemin SI N'EST dans le répertoire actuel). D'autres arguments peuvent être nécessaires en fonction du format des données. P> xxx pré>

2) grep / trouvatre strong> Une autre possibilité est d'utiliser Grep (Linux) ou FindStr (Windows) pour extraire les lignes avec AA code>. Cela devrait vous procurer les lignes souhaitées plus, éventuellement quelques autres et à ce stade, vous avez une entrée beaucoup plus petite, donc cela pourrait être sous-ensemble dans R sans problèmes de mémoire. Par exemple, P>

fread("csvfix find -if $1==aa File")  # Windows
fread("csvfix find -if '$1'==aa File")  # Linux bash


0 commentaires

0
votes

Si vous ne voulez pas muck avec SQL, envisagez d'utiliser l'argument code> Skip CODE> dans une boucle. Plus lent, mais de cette façon, vous lisez dans un bloc de lignes, filtrez-les, puis lisez dans le bloc de lignes suivant (à la même variable TEMP afin de ne pas prendre de mémoire supplémentaire), etc.
À l'intérieur de votre PApply code> appel, soit un second acadréal code> ou équivalent

for (jj in 0: N) {
    foo <-  fread(filename, skip = (jj*1000+1):((jj+1)*1000), sep=",", fill=TRUE, integer64="numeric",header=FALSE)
    mydata[[jj]] <- do_something_to_filter(foo)
}


0 commentaires