web-dev-qa-db-fra.com

Faire d'Int64 le dtype entier par défaut au lieu de l'int64 standard dans pandas

Je voudrais tous mes dataframes, qu'ils soient construits à partir de l'une des surcharges de constructeur, qu'ils soient dérivés de .read_csv(), .read_xlsx(), .read_sql(), ou toute autre méthode, pour utiliser le nouveau nullable Int64 type de données comme valeur par défaut dtype pour tous les entiers, plutôt que int64.

Je suis prêt à aller littéralement à n'importe quel niveau de folie pour le faire s'il n'y a pas de méthode `` sympa '', y compris le sous-classement des classes DataFrame ou Series, et la réimplémentation d'un certain nombre de méthodes et d'attributs de constructeur, etc.

Ma question est, cela peut-il être fait? Si oui, comment pourrais-je procéder?

17
matthewgdv

Je mettrais mon argent pour patcher des singes. Le moyen le plus simple serait de patcher le constructeur du DataFrame. Cela devrait ressembler à ceci:

import pandas
pandas.DataFrame.__old__init__ = pandas.DataFrame.__init__
def new_init(self, data=None, index=None, columns=None, dtype=pd.Int64Dtype(), copy=False):
    self.__old__init__(data=data, index=index, columns=None, dtype=dtype, copy=copy)

pandas.DataFrame.__init__ = new_init

Bien sûr, vous courez le risque de briser le monde. Bonne chance!

2
Joel

Vous pouvez utiliser une fonction comme celle-ci:

def nan_ints(df,convert_strings=False,subset = None):
    types = ['int64','float64']
    if subset is None:
        subset = list(df)
    if convert_strings:
        types.append('object')
    for col in subset:
        try:
            if df[col].dtype in types:
                df[col] = df[col].astype(float).astype('Int64')
        except:
            pass
    return df

Il parcourt chaque colonne et le recouvre en Int64 s'il s'agit d'un int. S'il s'agit d'un flottant, il ne se convertira en Int64 que si toutes les valeurs de la colonne peuvent être converties en entiers autres que les NaN. Je vous ai également donné la possibilité de convertir des chaînes en Int64 avec l'argument convert_strings .

df1 = pd.DataFrame({'a':[1.1,2,3,1],
                  'b':[1,2,3,np.nan],
                  'c':['1','2','3',np.nan],
                  'd':[3,2,1,np.nan]})


nan_ints(df1,convert_strings=True,subset=['b','c'])
df1.info()

Renvoie ce qui suit:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 4 columns):
a    4 non-null float64
b    3 non-null Int64
c    3 non-null Int64
d    3 non-null float64
dtypes: Int64(2), float64(2)
memory usage: 216.0 bytes

si vous comptez l'utiliser sur chaque DataFrame, vous pouvez ajouter la fonction à un module et l'importer à chaque fois que vous souhaitez utiliser des pandas. from my_module import nan_ints Ensuite, utilisez-le simplement avec quelque chose comme: nan_ints(pd.read_csv(path))

Remarque: Le type de données entier nul est Nouveau dans la version 0.24.0. Voici le documentation .

2
braintho