Lexpage - Essayez... Et vous perdrez du temps ! (mais que c'est bon de perdre du temps...)    —  Pierceb

Discussions

Python : apprentissage, ide, etc

yaug 1337 Spammeur
Reprise automatique du message précédent.
Bon, je suis confronté à une erreur qui semble commune mais que je n'arrive tout de même pas à gérer.
J'ai un fichier excel que je suis en train d'importer en base.
J'ai une des colonnes qui s'appelle "20_Contract size for derivatives"

Au niveau des valeurs, cela va souvent être vide, et parfois j'aurais un chiffre : 1, 100000, 34561.8

Je lis mon fichier avec pandas et je boucle les lignes de mon dataframe pour utiliser les données.
Je pensais pouvoir faire un row['20_Contract size for derivatives'] mais il me sort toujours une erreur :
KeyError: '20_Contract size for derivatives'
Alors même que j'ai bien une entrée à ce nom si je fais un print(row) :
20_Contract size for derivatives NaN

Si je comprend bien ma problématique, c'est qu'il considère que je ne peux pas accéder à ma colonne si j'ai une valeur nulle.
Du coup je suis passé par row.get('20_Contract size for derivatives')
Cela me renvoie un None, parfait.

Sauf qu'en fait non.
Si dans mon tuple j'ai cette valeur :
20_Contract size for derivatives                                                            1
et que je cherche à afficher le contenu de la colonne, j'ai quand même un "None" et l'accès en mode tableau me renvoie tout de même une KeyError

Une idée ?
Cela doit être évident mais ça fait une heure que je patine juste sur cette colonne, du coup j'ai du mal comprendre un truc je pense.
Merci :)


Ce message a été modifié 1 fois. Dernière modification : 12 septembre 2018 à 16:43 par yaug.

Guybrush 7781 Bob
Que te dit ton_df.columns ?
Je ne travaille pratiquement jamais avec iterrows (ou équivalent qui parcourt les lignes) parce que ce n'est pas très efficace, du coup je ne sais pas ce que ça donne quand on essaye d'accéder à un index via une row. Si y a une KeyError, c'est que la clé (colonne / valeur / index), peu importe que ça soit None, na ou une valeur. Le fait que ça te lance une exception n'est donc pas dû au fait que ça puisse être nul de temps en temps.

Mon hypothèse (mais je n'ai pas beaucoup d'éléments en main pour te répondre précisément), c'est que ce n'est ni un DataFrame (ce qui semble "évident" vu que tu parles de "row"), ni une Serie (ce que tu devrais avoir vu que tu parles de "row"). Pour le vérifier, fais un "type(row)", ça devrait donner une idée de ce que tu manipules réellement.

Question sous-jacente : comment obtiens-tu ces rows ? Via itertuples, iterrows,ou autre chose ?
yaug 1337 Spammeur
Hello
C'est pourtant bien une série : <class 'pandas.core.series.Series'>

J'accède à mes rows via :
df = pd.read_excel(aodb_excel, sheet_name = 'DataBase')
for index, row in df.iterrows():
create_object_from_row(row)
Et c'est dans ma fonction create_object_from_row que je vais mapper les rows de mon fichier excel à mon objet. Enfin que j'essaye :D
Guybrush 7781 Bob
Il doit y avoir un souci ailleurs, du coup :-D df.iterrows() retournant une série, et cette série étant une vue "horizontale" de ton DataFrame, son datatype est souvent object (un wrapper pour tout et n'importe quoi, ce qui permet d'avoir des entiers, réels, chaînes, etc.).

Est-ce que ta "colonne fantôme" apparait bien quand tu fais row.index ?
yaug 1337 Spammeur
Je ne me suis pas pris la tête, vu l'urgence du truc je suis passé sur itertuple qui lui ne me pose plus de problèmes :D

Désormais j'ai surtout des soucis de date entre Pandas et Peewee.
Les dates, la pire des choses en informatique


Ce message a été modifié 1 fois. Dernière modification : 13 septembre 2018 à 09:37 par yaug.

Guybrush 7781 Bob
itertuple est un poil plus rapide pour le coup (parce qu'il ne faut pas créer une série pour chaque ligne).

Pour la gestion des dates, c'est "curieux" dans le sens où les deux sont compatibles (import/export) vers datetime de Python.
yaug 1337 Spammeur
C'est moins curieux quand le problème vient des données en elle même ..
Quand je vois dans excel 31-12-99 je ne me pose pas de question.. sauf qu'en fait la valeur sous jacente c'est 31-12-9999 ...
D'où mes problèmes :D
Guybrush 7781 Bob
Si tu peux te permettre d'ignorer ces valeurs, alors ça peut être assez simple, car un des paramètres de pandas.to_datetime (paramètre errors) permet de définir le comportement à adopter en présence de "mauvaises dates". Par défaut, ça lève une exception ('raise'), mais tu peux choisir de simplement avoir un NaT à la place ('coerce') ou tout simplement de copier l'input ('ignore'), mais ça ne fait que déplacer le problème dans ce cas ;-)
yaug 1337 Spammeur
J'ai géré cela différemment car ces valeurs sont volontaires pour signaler un type d'objet. Donc en cas de valeur pourrave dans ce genre, je fou un boolean à true pour l'objet courant et je passe.
Pas simple d'importer des données depuis du excel fait par des financiers :D
Guybrush 7781 Bob
Tu peux simplement utiliser le paramètre 'coerce' pour avoir des NaT, et ensuite faire df['y a une valeur pourrave'] = df['date'].isnull() :-)


Ce message a été modifié 1 fois. Dernière modification : 13 septembre 2018 à 13:04 par Guybrush.

yaug 1337 Spammeur
Comme je commence à multiplier les lignes de codes, je m'approche du coup du besoin de séparer au maximum mon code.

Je me pose des questions sur comment organiser mon modèle de donnée par exemple.
je me suis fait un dossier model avec dedans model.py qui contient mes classes de modèle.
Mais du coup ça commence à devenir bien gros comme fichier et j'aimerais séparer en gardant une partie dans model.py et en créant pour chaque grosse classe un fichier grosseclasse.py, sachant que ces grosses classes utilisent des parties de model.py

par exemple dans model.py j'ai :
import peewee as pw

from config.config import db_config

database_proxy = pw.Proxy()

class MySQLModel(pw.Model):
"""A base model that will use our MySQL database"""
class Meta:
database = database_proxy
Si dans ept.py je déclare :
class EPT(MySQLModel):
uuid = pw.UUIDField(primary_key=True)
created_at = pw.DateTimeField(default=datetime.datetime.now, null=True)
updated_at = pw.DateTimeField(default=datetime.datetime.now, null=True)
share_class_id = pw.ForeignKeyField(ShareClass, null=True)
Ma classe dans le fichier model/ept.py ne connait pas ce qui est dans model/model.py
Du coup... un petit conseil sur comment bien gérer tout ça ?

Répondre

Vous devez être inscrit et identifié.