J'ai un très grand fichier csv que je dois lire. Pour rendre cela rapide et économiser l'utilisation de la RAM, j'utilise read_csv et je définis le dtype de certaines colonnes sur np.uint32. Le problème est que certaines lignes ont des valeurs manquantes et pandas utilise un flottant pour les représenter.

  1. Est-il possible de sauter simplement des lignes avec des valeurs manquantes? Je sais que je pourrais le faire après avoir lu tout le fichier, mais cela signifie que je ne pouvais pas définir le dtype jusque-là et utiliserais donc trop de RAM.
  2. Est-il possible de convertir les valeurs manquantes en une autre que je choisis lors de la lecture des données?
11
eleanora 8 août 2016 à 00:12

3 réponses

Meilleure réponse

Ce serait délicat si vous pouviez remplir NaN avec say 0 pendant la lecture elle-même. Peut-être qu'une demande de fonctionnalité dans le git-hub de Pandas est en ordre ...

Utilisation d'une fonction de convertisseur

Cependant, pour le moment, vous pouvez définir votre propre fonction pour ce faire et la passer à l'argument converters dans read_csv:

def conv(val):
    if val == np.nan:
        return 0 # or whatever else you want to represent your NaN with
    return val

df = pd.read_csv(file, converters={colWithNaN : conv}, dtypes=...)

Notez que converters prend un dict, vous devez donc le spécifier pour chaque colonne qui a NaN à traiter. Cela peut devenir un peu ennuyeux si de nombreuses colonnes sont affectées. Vous pouvez spécifier des noms de colonne ou des nombres comme clés.

Notez également que cela peut ralentir vos performances read_csv, selon la façon dont la fonction converters est gérée. De plus, si vous n'avez qu'une seule colonne qui nécessite la gestion des NaN pendant la lecture, vous pouvez ignorer une définition de fonction appropriée et utiliser une fonction lambda à la place:

df = pd.read_csv(file, converters={colWithNaN : lambda x: 0 if x == np.nan else x}, dtypes=...)

Lecture en morceaux

Vous pouvez également lire le fichier en petits morceaux que vous assemblez pour obtenir votre sortie finale. Vous pouvez faire un tas de choses de cette façon. Voici un exemple illustratif:

result = pd.DataFrame()
df = pd.read_csv(file, chunksize=1000)
for chunk in df:
    chunk.dropna(axis=0, inplace=True) # Dropping all rows with any NaN value
    chunk[colToConvert] = chunk[colToConvert].astype(np.uint32)
    result = result.append(chunk)
del df, chunk

Notez que cette méthode ne duplique pas strictement les données. Il y a un moment où les données de chunk existent deux fois, juste après l'instruction result.append, mais seules chunksize lignes sont répétées, ce qui est une bonne affaire. Cette méthode peut également s'avérer plus rapide qu'en utilisant une fonction de convertisseur.

10
Kartik 8 août 2016 à 05:48

Il n'y a aucune fonctionnalité dans Pandas qui fait cela. Vous pouvez l'implémenter en Python ordinaire comme ceci:

import csv
import pandas as pd

def filter_records(records):
    """Given an iterable of dicts, converts values to int.
    Discards any record which has an empty field."""

    for record in records:
        for k, v in record.iteritems():
            if v == '':
                break
            record[k] = int(v)
        else: # this executes whenever break did not
            yield record

with open('t.csv') as infile:
    records = csv.DictReader(infile)
    df = pd.DataFrame.from_records(filter_records(records))

Pandas utilise de toute façon le module csv en interne. Si les performances de ce qui précède s'avèrent être un problème, vous pouvez probablement l'accélérer avec Cython (que Pandas utilise également).

1
John Zwinck 7 août 2016 à 22:26

Si vous montrez des données, des personnes SO pourraient vous aider.

pd.read_csv('FILE', keep_default_na=False)

Pour commencer, essayez-les:

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html

na_values : str or list-like or dict, default None
Additional strings to recognize as NA/NaN. If dict passed, specific per-column NA values. By default the following values are interpreted as NaN: ‘’, ‘#N/A’, ‘#N/A N/A’, ‘#NA’, ‘-1.#IND’, ‘-1.#QNAN’, ‘-NaN’, ‘-nan’, ‘1.#IND’, ‘1.#QNAN’, ‘N/A’, ‘NA’, ‘NULL’, ‘NaN’, ‘nan’.

keep_default_na : bool, default True
If na_values are specified and keep_default_na is False the default NaN values are overridden, otherwise they’re appended to.

na_filter : boolean, default True
    Detect missing value markers (empty strings and the value of na_values). In data without any NAs, passing na_filter=False can improve the performance of reading a large file
-2
Merlin 7 août 2016 à 23:20