J'ai donc un fichier de données (séparé par des points-virgules) qui contient beaucoup de détails et de lignes incomplètes (ce qui fait que Access et SQL s'étranglent). Il s'agit d'un ensemble de données au niveau du comté, réparties en segments, sous-segments et sous-sous-segments (pour un total d'environ 200 facteurs) sur 40 ans. En bref, c'est énorme, et ça ne va pas tenir dans la mémoire si j'essaie de le lire simplement.
Ma question est donc la suivante : étant donné que je veux tous les comtés, mais seulement une seule année (et seulement le plus haut niveau de segment... ce qui donne environ 100 000 lignes à la fin), quelle serait la meilleure façon d'obtenir ce rollup dans R ?
Actuellement, j'essaie d'éliminer les années non pertinentes avec Python, en contournant la limite de taille des fichiers en lisant et en opérant sur une ligne à la fois, mais je préférerais une solution uniquement R (paquets CRAN OK). Existe-t-il un moyen similaire de lire dans les fichiers un morceau à la fois dans R ?
Toute idée serait grandement appréciée.
Mise à jour :
-
Contraintes
-
Besoin d'utiliser mon machine, donc pas d'instances EC2
-
Aussi R-only que possible. La vitesse et les ressources ne sont pas un souci dans ce cas... à condition que ma machine n'explose pas...
-
Comme vous pouvez le voir ci-dessous, les données contiennent des types mixtes, sur lesquels je dois opérer plus tard
-
Données
-
Les données représentent 3,5 Go, avec environ 8,5 millions de lignes et 17 colonnes.
-
Quelques milliers de lignes (~2k) sont mal formées, avec une seule colonne au lieu de 17.
-
Ils sont tout à fait insignifiants et peuvent être abandonnés.
-
Je n'ai besoin que d'environ 100 000 lignes de ce fichier (voir ci-dessous).
Exemple de données :
County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ...
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ...
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ...
NC [Malformed row]
[8.5 Mill rows]
Je veux supprimer certaines colonnes et choisir deux années parmi les 40 disponibles (2009-2010 de 1980-2020), afin que les données puissent être intégrées dans R :
County; State; Year; Quarter; Segment; GDP; ...
Ada County;NC;2009;4;FIRE;80.1; ...
Ada County;NC;2010;1;FIRE;82.5; ...
[~200,000 rows]
Résultats :
Après avoir bricolé avec toutes les suggestions faites, j'ai décidé que readLines, suggéré par JD et Marek, fonctionnerait mieux. J'ai donné le chèque à Marek parce qu'il a donné un exemple d'implémentation.
J'ai reproduit une version légèrement adaptée de l'implémentation de Marek pour ma réponse finale ici, en utilisant strsplit et cat pour ne garder que les colonnes que je veux.
Il convient également de noter qu'il s'agit BEAUCOUP moins efficace que Python... en effet, Python déchiquette le fichier de 3,5 Go en 5 minutes alors que R prend environ 60 minutes... mais si vous n'avez que R, c'est la solution.
## Open a connection separately to hold the cursor position
file.in <- file('bad_data.txt', 'rt')
file.out <- file('chopped_data.txt', 'wt')
line <- readLines(file.in, n=1)
line.split <- strsplit(line, ';')
# Stitching together only the columns we want
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
## Use a loop to read in the rest of the lines
line <- readLines(file.in, n=1)
while (length(line)) {
line.split <- strsplit(line, ';')
if (length(line.split[[1]]) > 1) {
if (line.split[[1]][3] == '2009') {
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
}
}
line<- readLines(file.in, n=1)
}
close(file.in)
close(file.out)
Défaillances par approche :
-
sqldf
-
C'est définitivement ce que j'utiliserai pour ce type de problème à l'avenir si les données sont bien formées. Cependant, si elles ne le sont pas, alors SQLite s'étrangle.
-
MapReduce
-
Pour être honnête, les docteurs m'ont un peu intimidé sur ce point, alors je n'ai pas eu le temps de l'essayer. Il semble que l'objet doive également être en mémoire, ce qui irait à l'encontre du but recherché si c'était le cas.
-
bigmemory
-
Cette approche permet d'établir un lien propre avec les données, mais elle ne peut traiter qu'un seul type à la fois. En conséquence, tous mes vecteurs de caractères sont tombés lorsqu'ils ont été placés dans un big.table. Si je devais concevoir de grands ensembles de données à l'avenir, j'envisagerais de n'utiliser que des nombres, juste pour conserver cette option.
-
balayage
-
Scan semble avoir le même type de problèmes que big memory, mais avec toute la mécanique de readLines. En bref, il n'a tout simplement pas fait l'affaire cette fois-ci.