Pandas: При использовании to_sql() продолжить, если обнаружены повторяющиеся первичные ключи?

Созданный на 13 апр. 2017  ·  19Комментарии  ·  Источник: pandas-dev/pandas

Образец кода, пример с возможностью копирования и вставки, если это возможно

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

Описание проблемы

Я пытаюсь добавить большой DataFrame в таблицу SQL. Некоторые строки в DataFrame дублируют строки в таблице SQL, некоторые нет. Но to_sql() полностью прекращает выполнение, если обнаружен хотя бы один дубликат.

Для to_sql(if_exists='append') имело бы смысл просто предупредить пользователя, в каких строках есть повторяющиеся ключи, и просто продолжить добавлять новые строки, а не полностью прекращать выполнение. Для больших наборов данных у вас, вероятно, будут дубликаты, но вы захотите их игнорировать.

Может быть, добавить аргумент, чтобы игнорировать дубликаты и продолжать выполнение? Возможно, дополнительная опция if_exists , например 'append_skipdupes' ?

Вывод pd.show_versions()

УСТАНОВЛЕННЫЕ ВЕРСИИ

фиксация: нет
питон: 3.6.0.финал.0
биты питона: 64
ОС: Windows
ОС-выпуск: 10
машина: AMD64
процессор: Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
порядок байтов: маленький
LC_ALL: нет
ЯЗЫК: Нет
МЕСТО: English_United States.1252

панды: 0.19.2
нос: Нет
пункт: 9.0.1
инструменты настройки: 28.8.0
Цитон: нет
номер: 1.12.0
scipy: нет
статистические модели: нет
рентген: нет
IPython: 5.3.0
сфинкс: нет
Пэтси: Нет
датаутилит: 2.6.0
питц: 2016.10
блок: нет
узкое место: нет
столы: нет
числовое выражение: нет
matplotlib: Нет
openpyxl: нет
XLRD: нет
xlwt: нет
xlsxwriter: нет
lxml: нет
бс4: Нет
html5lib: 0.999999999
httplib2: нет
апиклиент: нет
sqlalchemy: 1.1.9
pymysql: нет
psycopg2: нет
Джинджа2: 2.9.5
бото: нет
pandas_datareader: нет

Enhancement IO SQL

Самый полезный комментарий

Это также должно поддерживать режим «при дублирующем обновлении».

Все 19 Комментарий

Это также должно поддерживать режим «при дублирующем обновлении».

@rosstripi Я думаю, что идея иметь это, безусловно, будет принята, но, насколько мне известно, основным узким местом является реализация для этого с использованием sql/sqlalchemy, не зависящим от вкуса. Некоторое исследование того, как это можно сделать, безусловно, приветствуется!

Привет, ты нашел какой-нибудь обходной путь для этого? Пожалуйста, дай мне знать

Есть новости по этой реализации?

Сейчас я столкнулся с этой проблемой с PostgreSQL и SQLAlchemy и хотел бы иметь это «при дублирующем обновлении».

Спасибо за работу

Обходным путем может быть удаление уникального индекса в базе данных:

sqlquery="ALTER 'TABLE DATABASE'.'TABLE' DROP INDEX 'idx_name'"
после
df.to_sql('TableNameHere', engine, if_exists='append', chunksize=900, index=False)
может быть казнен.

Просто позвольте вашему серверу MySQL снова добавить индекс и удалить дубликаты.
sqlquery="ALTER IGNORE TABLE 'DATABASE'.'TABLE' ADD UNIQUE INDEX 'idx_name' ('column_name1' ASC, 'column_name2' ASC, 'column_name3' '[ASC | DESC]')"

В зависимости от вашего конкретного приложения это может быть полезно.
В любом случае вариант if_exists типа append_skipdupes был бы намного лучше.

append_skipdupes было бы идеальным способом справиться с этим.

да, append_skipdupes +1

Согласен, что было бы хорошо иметь возможность справиться с этим с опционами в df.to_sql() .

Вот обходной путь, который я использую в sqlite:

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

Затем, когда я вставляю дубликаты, они молча игнорируются, а не дубликаты обрабатываются правильно. В моем случае данные (т.е. должны быть ) статичны, поэтому мне не нужно их обновлять. Просто форма потока данных такова, что я получу дубликаты, которые можно игнорировать.

другой обходной путь с MariaDb и MySql:
df.to_csv("test.csv")
затем используйте:
LOAD DATA INFILE 'test.csv' IGNORE INTO TABLE mytable или
LOAD DATA INFILE 'test.csv' REPLACE INTO TABLE mytable .

ЗАГРУЗИТЬ ДАННЫЕ намного быстрее, чем ВСТАВИТЬ.

полный код:

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()))

Я полагаю, что это решается в #29636 с аргументом upsert_ignore , который обращается к #14553.

append_skipdupes +1

+1 за append_skipdupes

Согласитесь, что нужно добавить 'append_skipdupes'.

Да, пожалуйста. Следует добавить «append_skipdupes», и не только для столбца первичного ключа. Если среди других уникальных столбцов есть дубликаты, также следует пропустить добавление этих новых повторяющихся строк.

+1 за append_skipdupes

append_skipdupes +1

append_skipdupes +1

+1 за append_skipdupes

Тем временем вы можете использовать этот https://pypi.org/project/pangres/

Была ли эта страница полезной?
0 / 5 - 0 рейтинги