2
votes

Pandas ajoutant des points décimaux lors de l'utilisation de read_csv

Je travaille avec des fichiers csv et j'utilise des pandas pour les transformer en dataframe. Après cela, j'utilise une entrée pour trouver des valeurs à supprimer

Je suis accroché à un petit problème: pour certaines colonnes, il ajoute ".o" aux valeurs de la colonne. Il ne le fait que dans les colonnes avec des nombres, donc je suppose qu'il lit la colonne comme un flottant. Comment éviter que cela ne se produise?

Ce qui me déroute vraiment, c'est que cela ne se produit que dans quelques colonnes, donc je ne peux pas tout à fait comprendre un modèle. J'ai besoin de couper le ".0" pour pouvoir le réimporter, et je pense qu'il serait plus facile de l'empêcher de se produire en premier lieu.

Merci!

Voici un exemple de mon code:

clientid = int(input('What client ID needs to be deleted?'))

df1 = pd.read_csv('Client.csv')
clientclean = df1.loc[df1['PersonalID'] != clientid]
clientclean.to_csv('Client.csv', index=None)

Idéalement, j'aimerais que toutes les valeurs soient identiques à celles du fichier csv d'origine, mais sans les lignes avec le clientid à partir de l'entrée utilisateur.

La partie qui me déroute vraiment est que cela ne se produit que dans quelques colonnes, donc je ne peux pas tout à fait comprendre un modèle. J'ai besoin de couper le ".0" pour pouvoir le réimporter, et je pense qu'il serait plus facile de l'empêcher de se produire en premier lieu.

Merci!


4 commentaires

S'agit-il d'une chaîne ".o" , ou est-ce simplement une importation sous forme de flottant, .0 décimal? Ce n'est pas clair dans votre description


Peut-être que l'utilisation du paramètre dtype de la fonction read_csv suffira-t-elle à régler cela? dtype = {'PersonalID': np.int32}


Le problème sous-jacent est qu'il n'y a pas de support np.NaN pour les entiers, donc si vous avez une colonne avec des nombres et des valeurs manquantes, elles sont converties en float et 12345 devient < code> 12345.0 . Les petits entiers peuvent être parfaitement représentés avec float64 , vous n'avez donc pas à vous soucier des inexactitudes avec les comparaisons d'égalité en virgule flottante.


C'est un flotteur. Par exemple, dans une colonne, une valeur est "99", mais après l'avoir exécutée dans le code, elle est convertie en "99.0"


3 Réponses :


0
votes

Si PersonalID est l'en-tête de la colonne problématique, essayez ceci:

df1[col] = df1[col].fillna(-9999) # or 0 or any value you want here
df1[col] = df1[col].astype(int)

Modifier: Comme il n'y a pas de valeur NaN pour entier. Vous pouvez essayer ceci sur chaque colonne problématique:

df1 = pd.read_csv('Client.csv', dtype={'PersonalID':np.int32})


9 commentaires

doit probablement être converti en objet car vous ne pouvez pas avoir de colonne int32 avec des valeurs manquantes.


Ce n'est en fait pas la colonne PersonalID. J'ai d'abord remarqué deux autres colonnes, les deux entiers. Les valeurs nulles se produisent dans ces colonnes, mais vous avez raison, chaque client doit avoir un clientid.


Si chaque client avait un ClientID , alors pandas réduirait la colonne en un entier lorsqu'il la lit. La seule raison pour laquelle il existe en tant que flottant est qu'il ne peut pas convertir la colonne en un entier, mais la colonne a tous les types numériques (et les valeurs manquantes), qui sont converties en toute sécurité en float


Si tel est le cas, souhaitez-vous conserver les valeurs na?


Oui, j'aimerais garder les valeurs na. Je me demande s'il serait plus facile d'utiliser .astype (objet) pour changer toutes les colonnes en objets et m'assurer de ne rien manquer.


Vérifiez ma modification, c'est peut-être quelque chose que vous pourriez faire si vous voulez vraiment un entier.


Et si vous voulez vraiment garder les valeurs NaN comme NaN et pas autre chose, le type d'objet est celui dont vous avez besoin


Je l'ai testé sur quelques-uns, et ça marche! Existe-t-il un moyen plus rapide d'attribuer le type de données? Je voudrais simplement le définir pour toutes les colonnes au lieu de le spécifier manuellement, car cela sera fastidieux et prend du temps.


Si vous voulez que toutes les colonnes soient int: df1.astype (int) devrait faire. (Ne spécifiez simplement pas la colonne et les pandas le feront pour toutes les données)



0
votes

Vous pouvez parcourir chaque valeur, et s'il s'agit d'un nombre x , en soustraire int (x) , et si cette différence n'est pas 0,0, convertir le nombre x à int (x) . Ou, si vous ne traitez pas avec des non-entiers, vous pouvez simplement convertir toutes les valeurs qui sont des nombres en int s.

Pour un exemple de ce dernier (lorsque vos données d'origine contiennent des nombres non entiers):

import numbers
import sys

for c, col in enumerate(df1.columns):
    foundNonInt = False
    for r, index in enumerate(df1.index):
        if isinstance(x, float):
            if (x - int(x) > sys.float_info.epsilon):
                foundNonInt = True
                    break
    if (foundNonInt==False):
        df1.iloc[:,c] = int(df1.iloc[:,c])
    else:

Pour un exemple du premier (si vous voulez garder les nombres non entiers comme des nombres non entiers, mais voulez garantir que les nombres entiers restent comme des entiers):

for index, row in df1.iterrows():
    for c, x in enumerate(row):
        if isinstance(x, float):
            df1.iloc[index,c] = int(x)

Remarque, la méthode ci-dessus n'est pas infaillible: si par hasard, une colonne de nombres non entiers de l'ensemble de données d'origine contient non -entiers qui sont tous x.0000000, jusqu'à la dernière décimale, cela échouera.


0 commentaires

1
votes

C'était un problème de type de données.

Le commentaire d'ALollz m'a conduit dans la bonne direction. Pandas supposait un type de données flottant, qui ajoutait les points décimaux.

J'ai spécifié le type de données comme objet (d'après le commentaire d'Akarius) lors de l'utilisation de read_csv, ce qui a résolu le problème.


0 commentaires