Python SQLAlchemy Tech

Python NaNを含むデータをMySQLに保存したいとき(コードとエラー対処)

Pythonでデータ処理した後にMySQLなどのデータベースに保存する操作の話題です。

Pythonにまだ慣れていないという人でも、Pandasなどで処理したデータをデータベースとやり取りする経験はあるのではないでしょうか。

今回の記事では、Pandasのデータ(DataFrameやSeries)にNaNNoneが含まれているときにMySQLからエラーが返ってきたときの対処法をまとめています。

検証環境

Python 3.9
Pandas 1.2.3
SQLAlchemy 1.4.5
PyMySQL 1.0.2

 

nan can not be used with MySQLエラーに対処する

このようなエラーが出ましたか?

sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) nan can not be used with MySQL

これは、NaNを含むデータをMySQLにUPDATEまたはINSERTしようとしたときに発生します。

エラーを再現してみます。

 

まずは適当なデータ(カンマ区切りのテキストファイル形式)を用意し、読み込ませます。

csv = ("tag,name\n"
    + "A,Alpha\n"
    + "B,Bravo\n"
    + "C,\n"
    + "D,Delta\n")
stream = io.StringIO(csv)
df = pd.read_csv(stream)

 

1行目はヘッダーとして扱います。
今回、4行目(tag='C')のname列を空欄としました。

pandas.read_csv で読み込むと、空欄(空文字)のところは自動でNaN(np.nan)になります。

printして見てみます。

print(df)

#   tag   name
# 0   A  Alpha
# 1   B  Bravo
# 2   C    NaN    # 空欄の部分はNaNに
# 3   D  Delta

 

次に、このdf をそのままSQLAlchemyのORMでaddしようとすると…

for _, d in df.iterrows():
    tag = TagName(tag=d['tag'], name=d['name'])
    session.add(tag)
session.commit()

 

こんな感じのエラーとなります。

sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) nan can not be used with MySQL
[SQL: INSERT INTO tag_names (tag, name) VALUES (%(tag)s, %(name)s)]
[parameters: {'tag': 'C', 'name': nan}]
(Background on this error at: http://sqlalche.me/e/14/f405)

 

nan は MySQLでは扱えないよ!と怒られてしまいました。

そのままだと保存できないので、None などに変換してあげましょう

import numpy as np

df = df.replace({np.nan: None})

 

これで、もう一度 add / commitを実行してみると正常に挿入が完了します。

MySQL側をみれば、空欄だったところがnullで保存されているはずです。

 

Pythonのスキルを使って毎月の収入源を増やすのが最適なんじゃないかという件

実際、今のスキルに合わせて仕事を獲得し、スキマ時間で毎月+5、+20、+70万円くらいの人が多いです。

必要なスキル、仕事の獲得までの流れは以下の記事で徹底解説しています。
もちろん全部無料です
空いた時間にぜひ参考にしてみてください。

 

pandasa.to_sql()でNaNをnullとしてINSERT

ちなみに別の方法もあります。

SQLAlchemy ORMではなくCoreでinsertすればnanのままでも更新操作ができます。

engine = get_engine()
df.to_sql(
    'tag_names',  # テーブル名
    con=engine,
    schema='playground',
    if_exists='append',
    index=False
)

 

DataFrameの中身をデータベースに書き込む pandas.to_sql()メソッドを使っています。

この場合も、nanだった部分がMySQLにはnullとして保存されます。

 

雑記

ちなみにPythonの世界ではNoneNaNはそれぞれ違うものです。

これらの違いはこちらのまとめを参考にしてみてください。

 

  • この記事を書いた人

次世代ペンギン

長いのでペンギンとお呼びください。システム開発・プログラミングのお仕事をしています。甘味とコーヒーは生命線。多くの人に役立つ情報のシェアが目標です。

人気の記事

1

会社員でプログラマーとして働いている人、インフラやネットワークのエンジニアとして働いている人の中には、フリーランスのプログラマーとして独立、もしくは転向したい人もいるので ...

2

キャリアアップのため、または高収入を目指して、しっかりプログラミングを学びたいという人が増えてきましたね。 この記事では現役のエンジニアである私が、実際に仕事で稼げるよう ...

3

フリーランスのプログラマーにとって収入の向上に最も直結するのはスキルです。 必要なスキル、スキルの獲得方法が気になる人も多いでしょう。 また、これからフリーランスを目指す ...

4

Vuetifyの v-progress-circular コンポーネントは、数値データや処理状況を環状(円状)のデザインで教えてくれるUIデザインです。 ローディングのス ...

5

Vuexのstore(ストア)を使うと、各コンポーネント間で個別にデータのやり取りすることなく、データを一元的に管理できます。Vueでは欠かせない機能といえるでしょう。 ...

-Python, SQLAlchemy, Tech
-, , ,