Reputation: 637
After learning I have to apply the converters
argument (and not dtype
) to have a pandas column of decimal.Decimal
class, I tried doing it with a module I'm using to access SQLite databases. However, while this argument is implemented in pd.read_csv
and is available as a kwarg in pd.read_excel
, that is not the case with pd.read_sql
:
In [1]: df = pd.read_sql('SELECT * FROM table', myconnection, converters={'somecol':decimal.Decimal})
Traceback (most recent call last):
File "<ipython-input-13-abdc559366bb>", line 1, in <module>
pd.read_sql('SELECT * FROM table', myconnection, converters={'somecol':decimal.Decimal})
TypeError: read_sql() got an unexpected keyword argument 'converters'
Is there any way to do the conversion natively? The documentation for the function indicates pd.read_sql
doesn't allow for any kwargs at all.
If not possible, which would be the most recommended solution? I could do with df['somecol'] = df['somecol'].apply(decimal.Decimal)
, but I'm wondering if there is a less verbose way in this case.
Upvotes: 1
Views: 718
Reputation: 637
The solution is found in SQLite3's own documentation, through the register_converter
function and then calling an argument on the connection:
import sqlite3
from decimal import Decimal
def conv(i):
# Converts a number input to decimal.
return Decimal(str(i))
sqlite3.register_converter('REAL', conv)
con = sqlite3.connect('something.db', detect_types=sqlite3.PARSE_DECLTYPES)
This way all numbers stored as real in SQLite will be automatically converted to Decimal
upon reading.
Obs: note that the string conversion before decimal in the conv
function happens in order to preserve the state of the number (although calling conv(1.1+2.2)
will result in badly-formed decimals anyway.
Upvotes: 2