df.to_sql('TableNameHere', engine, if_exists='append', chunksize=900, index=False)
Estou tentando anexar um grande DataFrame a uma tabela SQL. Algumas das linhas no DataFrame são duplicatas daquelas na tabela SQL, outras não. Mas to_sql()
para completamente de executar se até mesmo uma duplicata for detectada.
Faria sentido para to_sql(if_exists='append')
apenas avisar o usuário quais linhas tinham chaves duplicadas e apenas continuar a adicionar as novas linhas, não parar completamente a execução. Para grandes conjuntos de dados, você provavelmente terá duplicatas, mas deseja ignorá-las.
Talvez adicionar um argumento para ignorar duplicatas e continuar executando? Talvez uma opção adicional if_exists
como 'append_skipdupes'
?
pd.show_versions()
compromisso: Nenhum
python: 3.6.0.final.0
bits python: 64
SO: Windows
Versão do SO: 10
máquina: AMD64
processador: Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
byteorder: pouco
LC_ALL: Nenhum
LAN: Nenhum
LOCAL: Inglês_Estados Unidos.1252
pandas: 0,19,2
nariz: nenhum
pip: 9.0.1
ferramentas de configuração: 28.8.0
Cíton: Nenhum
numpy: 1.12.0
cip: Nenhum
statsmodels: Nenhum
xarray: Nenhum
IPython: 5.3.0
esfinge: Nenhuma
Paty: Nenhum
dateutil: 2.6.0
pytz: 2016.10
bloco: Nenhum
gargalo: nenhum
tabelas: Nenhuma
numexpr: Nenhum
matplotlib: Nenhum
openpyxl: Nenhum
xlrd: Nenhum
xlwt: Nenhum
xlsxwriter: Nenhum
lxml: Nenhum
bs4: Nenhum
html5lib: 0,999999999
httplib2: Nenhum
apiclient: Nenhum
sqlalchemy: 1.1.9
pymysql: Nenhum
psycopg2: Nenhum
jinja2: 2.9.5
boto: nenhum
pandas_datareader: Nenhum
Isso também deve suportar o modo "na atualização duplicada".
@rosstripi Acho que a ideia de ter isso certamente seria aceita, mas AFAIK o principal gargalo é uma implementação para isso usando sql/sqlalchemy de maneira agnóstica de sabor. Alguma exploração de como isso poderia ser feito é certamente bem-vinda!
Olá, você conseguiu alguma solução para isso? Por favor deixe-me saber
Alguma atualização sobre essa implementação?
Agora estou enfrentando esse problema com o PostgreSQL e SQLAlchemy e adoraria ter isso "na atualização duplicada".
Obrigado pelo trabalho
Uma solução alternativa seria remover o índice exclusivo no banco de dados:
sqlquery="ALTER 'TABLE DATABASE'.'TABLE' DROP INDEX 'idx_name'"
após
df.to_sql('TableNameHere', engine, if_exists='append', chunksize=900, index=False)
pode ser executado.
Apenas deixe seu servidor MySQL adicionar o índice novamente e elimine as duplicatas.
sqlquery="ALTER IGNORE TABLE 'DATABASE'.'TABLE' ADD UNIQUE INDEX 'idx_name' ('column_name1' ASC, 'column_name2' ASC, 'column_name3' '[ASC | DESC]')"
Dependendo de sua aplicação específica, isso pode ser útil.
De qualquer forma if_exists
opção como append_skipdupes
seria muito melhor.
append_skipdupes
seria a maneira perfeita de lidar com isso.
sim, append_skipdupes +1
Concordei que seria bom poder lidar com isso com opções em df.to_sql()
.
Aqui está a solução que eu uso no sqlite:
CREATE TABLE IF NOT EXISTS my_table_name (
some_kind_of_id INT PRIMARY KEY ON CONFLICT IGNORE,
...
Então, quando insiro duplicatas, elas são ignoradas silenciosamente e as não duplicadas são processadas corretamente. No meu caso, os dados são (ou seja , deveriam ser ) estáticos, então não preciso atualizar. É só que a forma do feed de dados é tal que obterei duplicatas que são ignoráveis.
uma outra solução alternativa com MariaDb e MySql:
df.to_csv("test.csv")
então use:
LOAD DATA INFILE 'test.csv' IGNORE INTO TABLE mytable
ou
LOAD DATA INFILE 'test.csv' REPLACE INTO TABLE mytable
.
LOAD DATA é muito mais rápido que INSERT.
código completo:
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()))
Acredito que isso esteja sendo abordado em #29636 com o argumento upsert_ignore
, que aborda #14553.
append_skipdupes +1
+1 para append_skipdupes
Concordo que 'append_skipdupes' deve ser adicionado.
Sim por favor. 'append_skipdupes' deve ser adicionado e não apenas para a coluna Chave Primária. Se houver duplicatas entre outras colunas exclusivas, também deve pular a adição dessas novas linhas duplicadas.
+1 para append_skipdupes
append_skipdupes +1
append_skipdupes +1
+1 para append_skipdupes
Enquanto isso, você pode usar isso https://pypi.org/project/pangres/
Comentários muito úteis
Isso também deve suportar o modo "na atualização duplicada".