Pandas: Lors de l'utilisation de to_sql(), continuer si des clés primaires en double sont détectées ?

Créé le 13 avr. 2017  ·  19Commentaires  ·  Source: pandas-dev/pandas

Exemple de code, un exemple à copier-coller si possible

df.to_sql('TableNameHere', engine, if_exists='append', chunksize=900, index=False)

Description du problème

J'essaie d'ajouter un grand DataFrame à une table SQL. Certaines des lignes du DataFrame sont des doublons de celles de la table SQL, d'autres non. Mais to_sql() s'arrête complètement de s'exécuter même si un seul doublon est détecté.

Il serait logique que to_sql(if_exists='append') avertisse simplement l'utilisateur des lignes contenant des clés en double et continue simplement à ajouter les nouvelles lignes, sans arrêter complètement l'exécution. Pour les grands ensembles de données, vous aurez probablement des doublons, mais vous voudrez les ignorer.

Peut-être ajouter un argument pour ignorer les doublons et continuer à s'exécuter ? Peut-être une option if_exists supplémentaire comme 'append_skipdupes' ?

Sortie de pd.show_versions()

VERSIONS INSTALLÉES

validation : aucune
Python : 3.6.0.final.0
python-bits : 64
Système d'exploitation : Windows
Version du système d'exploitation : 10
ordinateur : AMD64
processeur : Intel64 famille 6 modèle 60 Stepping 3, GenuineIntel
ordre des octets : peu
LC_ALL : aucun
LANGUE : Aucune
LOCALE : anglais_États-Unis.1252

pandas : 0.19.2
nez : Aucun
pip : 9.0.1
outils de configuration : 28.8.0
Cyton : Aucun
numérique : 1.12.0
scipy : aucun
modèles de statistiques : aucun
xarray : aucun
IPython : 5.3.0
sphinx : Aucun
patty : Aucun
dateutil : 2.6.0
pytz : 2016.10
bloc: Aucun
goulot d'étranglement : aucun
tableaux : aucun
numexpr : Aucun
matplotlib : aucun
openpyxl : Aucun
xlrd : aucun
xlwt : aucun
xlsxwriter : Aucun
lxml : Aucun
bs4 : aucun
html5lib : 0,999999999
httplib2 : aucun
client API : Aucun
sqlalchimie : 1.1.9
pymysql : aucun
psycopg2 : aucun
jinja2 : 2.9.5
boto : Aucun
pandas_datareader : aucun

Enhancement IO SQL

Commentaire le plus utile

Cela devrait également prendre en charge le mode "sur la mise à jour en double".

Tous les 19 commentaires

Cela devrait également prendre en charge le mode "sur la mise à jour en double".

@rosstripi Je pense que l'idée d'avoir cela serait certainement acceptée, mais AFAIK, le principal goulot d'étranglement est une implémentation pour cela en utilisant sql/sqlalchemy d'une manière agnostique. Une exploration de la manière dont cela pourrait être fait est certainement la bienvenue !

Salut, avez-vous trouvé une solution de contournement pour cela? s'il vous plaît, faites-moi savoir

Une mise à jour sur cette implémentation?

Je suis maintenant confronté à ce problème avec PostgreSQL et SQLAlchemy et j'aimerais avoir cela "sur une mise à jour en double".

Merci pour le travail

Une solution consisterait à supprimer l'index unique dans la base de données :

sqlquery="ALTER 'TABLE DATABASE'.'TABLE' DROP INDEX 'idx_name'"
après
df.to_sql('TableNameHere', engine, if_exists='append', chunksize=900, index=False)
peut être exécuté.

Laissez simplement votre serveur MySQL ajouter à nouveau l'index et supprimez les doublons.
sqlquery="ALTER IGNORE TABLE 'DATABASE'.'TABLE' ADD UNIQUE INDEX 'idx_name' ('column_name1' ASC, 'column_name2' ASC, 'column_name3' '[ASC | DESC]')"

Selon votre application spécifique, cela peut être utile.
Quoi qu'il en soit, une option if_exists comme append_skipdupes serait bien meilleure.

append_skipdupes serait le moyen idéal pour gérer cela.

oui, append_skipdupes +1

Convenu qu'il serait bon de pouvoir gérer cela avec des options dans df.to_sql() .

Voici la solution de contournement que j'utilise dans sqlite :

CREATE TABLE IF NOT EXISTS my_table_name (
    some_kind_of_id INT PRIMARY KEY ON CONFLICT IGNORE,
    ...

Ensuite, lorsque j'insère des doublons, ils sont ignorés en silence et les non-doublons sont traités correctement. Dans mon cas, les données sont (c'est-à-dire devraient être ) statiques, donc je n'ai pas besoin de mettre à jour. C'est juste que la forme du flux de données est telle que j'obtiendrai des doublons ignorables.

une autre solution de contournement avec MariaDb et MySql :
df.to_csv("test.csv")
puis utilisez :
LOAD DATA INFILE 'test.csv' IGNORE INTO TABLE mytable ou
LOAD DATA INFILE 'test.csv' REPLACE INTO TABLE mytable .

LOAD DATA est beaucoup plus rapide que INSERT.

code complet :

csv_path = str(Path(application_path) / "tmp" / "tmp.csv").replace("\\", "\\\\")
df.to_csv(csv_path, index=False, sep='\t', quotechar="'", na_rep=r'\N')
rq = """LOAD DATA LOCAL INFILE '{file_path}' REPLACE INTO TABLE {db}.{db_table}
        LINES TERMINATED BY '\\r\\n'
        IGNORE 1 LINES
         ({col});
        """.format(db=db,
                   file_path=csv_path,
                   db_table=table_name,
                   col=",".join(df.columns.tolist()))

Je crois que cela est traité dans # 29636 avec l'argument upsert_ignore , qui adresse #14553.

append_skipdupes +1

+1 pour append_skipdupes

D'accord, 'append_skipdupes' doit être ajouté.

Oui s'il vous plaît. 'append_skipdupes' doit être ajouté et pas seulement pour la colonne Clé primaire. S'il y a des doublons parmi d'autres colonnes uniques, il convient également d'ignorer l'ajout de ces nouvelles lignes en double.

+1 pour append_skipdupes

append_skipdupes +1

append_skipdupes +1

+1 pour append_skipdupes

En attendant, vous pouvez utiliser ce https://pypi.org/project/pangres/

Cette page vous a été utile?
0 / 5 - 0 notes