我正在捆绑批量插入一个数据文件到我的postgres dB。我的dataframe中的某些列是日期类型,
NaT
为空值。这是PostgreSQL不支持的,我尝试用其他空类型标识替换
NaT
(使用熊猫),但在插入过程中不起作用。
我使用
df = df.where(pd.notnull(df), 'None')
替换了所有的
NaT
,例如由于数据类型问题而不断出现的错误。
Error: invalid input syntax for type date: "None"
LINE 1: ...0,1.68757,'2022-11-30T00:29:59.679000'::timestamp,'None','20...
我的驱动程序和插入语句到postgresql dB:
def execute_values(conn, df, table):
Using psycopg2.extras.execute_values() to insert the dataframe
# Create a list of tupples from the dataframe values
tuples = [tuple(x) for x in df.to_numpy()]
# Comma-separated dataframe columns
cols = ','.join(list(df.columns))
# SQL quert to execute
query = "INSERT INTO %s(%s) VALUES %%s" % (table, cols)
cursor = conn.cursor()
extras.execute_values(cursor, query, tuples)
conn.commit()
except (Exception, psycopg2.DatabaseError) as error:
print("Error: %s" % error)
conn.rollback()
cursor.close()
return 1
print("execute_values() done")
cursor.close()
有关我的dataframe的信息:在本例中,罪魁祸首仅为datetime列。
这通常是如何解决的?
发布于 2021-01-29 16:20:37
关于您原来的更新声明:
df = df.where(pd.notnull(df), 'None')
这里发生的是用字符串' None‘替换值,而不是用特殊的Python对象None替换值。然后在下面的insert语句中,尝试将字符串'None‘插入时间戳字段并引发错误。
有趣的是,你所期望的这个版本是可行的:
df = df.where(pd.notnull(df), None)
实际上,由于我不完全理解的原因,NaT值似乎不像预期的那样工作。(见下文示例)
但是,看起来起作用的是这样的语句(假设您将numpy导入为np):
df = df.replace({np.NaN: None})
因此,如果这样做,那么NaN和NaT值都将转换为Python,然后psycopg2 (或者任何其他db连接器)将正确地将这些值作为插入的SQL对待。
下面是一些示例代码来说明:
import datetime as dt
import pandas as pd
import numpy as np
data = [
['one', 1.0, pd.NaT],
['two', np.NaN, dt.datetime(2019, 2, 2)],
[None, 3.0, dt.datetime(2019, 3, 3)]
df = pd.DataFrame(data, columns=["Name", "Value", "Event_date"])
得到了我们的基本数据
>>> df
Name Value Event_date
0 one 1.0 NaT
1 two NaN 2019-02-02
2 None 3.0 2019-03-03
如前所述,由于某些原因,此更新将NaT保留在其中:
>>> df.where(pd.notnull(df), None)
Name Value Event_date
0 one 1.0 NaT
1 two None 2019-02-02
2 None 3.0 2019-03-03
但是这个版本同时获得了NaNs和NaTs,并留下了预期的Nones:
>>> df.replace({np.NaN: None})
Name Value Event_date
0 one 1.0 None
1 two None 2019-02-02 00:00:00
2 None 3.0 2019-03-03 00:00:00
接受的答案可能是“更好”的方式,如果你可以使用sqlalchemy来做你想做的事情,但是如果你要用艰苦的方式去做,这对我是有效的。
H/T到 关于大熊猫问题的讨论 获得这个答案的大部分细节。
发布于 2022-04-13 08:43:10
如果不能使用
pandas
的
to_sql
方法,则可以用
psycopg
代替
注册适配器
:
import pandas as pd
from psycopg2.extensions import register_adapter, AsIs
# Register adapter for pandas NA type (e.g. null datetime or integer values)