これは、jaydebeapiを使用するときに問題になるようです jpypeを使用 。これは、Oracleデータベースに接続するときに同じ方法で再現できます(私の場合はOracle 11gR2ですが、ojdbc8.jarを使用しているためです。 、他のバージョンでも発生すると思います。
これを解決するにはさまざまな方法があります:
接続を変更する
エラーはパッケージの特定の組み合わせでのみ発生するように思われるため、最も賢明な方法は、これらを回避してエラーを完全に回避することです。
-
代替1:
jaydebeapiを使用するjpypeなし :前述のように、私は
jaydebeapiを使用する場合にのみこれを観察しますjpypeを使用 。ただし、私の場合、jpypeまったく必要ありません。.jarがあります ファイルをローカルに保存すると、接続がなくても正常に機能します:import jaydebeapi as jdba import pandas as pd import os db_host = 'db.host.com' db_port = 1521 db_sid = 'YOURSID' jar=os.getcwd()+'/ojdbc6.jar' conn = jdba.connect('oracle.jdbc.driver.OracleDriver', 'jdbc:oracle:thin:@' + db_host + ':' + str(db_port) + ':' + db_sid, {'user': 'USERNAME', 'password': 'PASSWORD'}, jar ) df_jay = pd.read_sql('SELECT * FROM YOURSID.table1', conn) conn.close()私の場合、これは正常に機能し、データフレームを正常に作成します。
-
代替2:
cx_Oracleを使用する 代わりに:cx_Oracleを使用しても、この問題は発生しません。 Oracleデータベースに接続するには:import cx_Oracle import pandas as pd import os db_host = 'db.host.com' db_port = 1521 db_sid = 'YOURSID' dsn_tns = cx_Oracle.makedsn(db_host, db_port, db_sid) cx_conn = cx_Oracle.connect('USERNAME', 'PASSWORD', dsn_tns) df_cxo = pd.read_sql('SELECT * FROM YOURSID.table1', con=cx_conn) cx_conn.close()注:
cx_Oracleの場合 動作するには、 Oracle InstantClient が必要です。 インストールされ、適切にセットアップされている(例:Ubuntuのcx_Oracleドキュメント 。
事後のデータフレームを修正:
何らかの理由で上記の代替接続を使用できない場合は、データフレームを変換することもできます。
-
代替3:タプルエントリを結合する:
''.join()を使用できます タプルを文字列に変換 する 。エントリと列名に対してこれを行う必要があります。# for all entries that are not None, join the tuples for col in df.select_dtypes(include=['object']).columns: df[col] = df[col].apply(lambda x: ''.join(x) if x is not None else x) # also rename the column headings in the same way df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True) -
代替4:列のdtypeを変更する:
dtypeを変更するobjectからの影響を受ける列のstringへ 、すべてのエントリも変換されます。これには、たとえば次のような望ましくない副作用がある可能性があることに注意してください。Noneの変更 文字列の値<N/A>。また、上記のように、列見出しの名前を個別に変更する必要があります。for col in df.select_dtypes(include=['object']).columns: df[col] = df[col].astype('string') # again, rename headings df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
これらはすべて、ほぼ同じdfを生成するはずです。 最後に(dtypesは別として) Noneの可能な置換 値):
+---+---------+---------+---------+
| | COLUMN1 | COLUMN2 | COLUMN3 |
+---+---------+---------+---------+
| 1 | test | test2 | 1 |
+---+---------+---------+---------+
| 2 | foo | bar | 100 |
+---+---------+---------+---------+