df.to_sql('TableNameHere', engine, if_exists='append', chunksize=900, index=False)
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'
?
pd.show_versions()
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
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/
Commentaire le plus utile
Cela devrait également prendre en charge le mode "sur la mise à jour en double".