Zhe*_*ENG 5 database dataframe pandas clickhouse clickhouse-client
我正在尝试将 Pandas 数据框插入 Clickhouse,但遇到了一些问题。\n以下是表架构:
\nCREATE TABLE IF NOT EXISTS test_table\n(\n name String,\n day DateTime64(3) DEFAULT \'2020-07-01 00:00:00\',\n)\nengine = MergeTree\nORDER BY (name, day);\nRun Code Online (Sandbox Code Playgroud)\npandas dataframe 中的数据如下:
\n name day\n0 \'a\' NaT\n1 \'b\' NaT\n2 \'c\' \'2019-08-31 00:00:00\'\nRun Code Online (Sandbox Code Playgroud)\n插入的python代码是:
\nfrom clickhouse_driver import Client\nwith Client(host="", port="", password="",\n user="", settings={"use_numpy": True}) as client:\n client.insert_dataframe(\n \'INSERT INTO test_table VALUES\',\n df)\nRun Code Online (Sandbox Code Playgroud)\nclickhouse中的结果是
\nSELECT *\nFROM test_table\n\n\xe2\x94\x8c\xe2\x94\x80name\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80day\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 a \xe2\x94\x82 1970-01-01 00:00:00.000\xe2\x94\x82\n\xe2\x94\x82 b \xe2\x94\x82 1970-01-01 00:00:00.000\xe2\x94\x82\n\xe2\x94\x82 c \xe2\x94\x82 2019-08-31 00:00:00.000\xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\nRun Code Online (Sandbox Code Playgroud)\n但我真正想要的是它是默认值,意味着 \'1970-01-01 00:00:00.000\' 将被替换为 \'2020-07-01 00:00:00.000\' 。
\n我做了一些尝试和调查,以下是我所做的:
\ndf.replace({pd.NaT: None}, inplace=True)\nor\ndf1.replace({pd.NaT: np.NaN}, inplace=True)\nRun Code Online (Sandbox Code Playgroud)\n但这些改变的结果仍然是一样的
\ninsert into test_table (name,day) values (\'test-null\',null);\nor\ninsert into test_table (name) values (\'test-sub\');\n\n\n\xe2\x94\x8c\xe2\x94\x80name\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80day\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 test-null \xe2\x94\x82 2020-07-01 00:00:00.000\xe2\x94\x82\n\xe2\x94\x82 test-sub \xe2\x94\x82 2020-07-01 00:00:00.000\xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n\nRun Code Online (Sandbox Code Playgroud)\ninsert into test_table (name,day) values (\'test-empty\',\'\');\n\nSELECT *\nFROM test_table\n\n\xe2\x94\x8c\xe2\x94\x80name\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80day\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 test-empty \xe2\x94\x82 1970-01-01 00:00:00.000\xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\nRun Code Online (Sandbox Code Playgroud)\n所以,我现在所做的只是将数据帧分成两部分,然后插入两次(我认为这不是Pythonic和高效的),但它确实可以工作
\n# select not null rows\nmask1 = ~np.isnan(df.day.values)\n\n# select null rows\nmask3 = np.isnan(df.day.values)\n\nwith Client(host="", port="", password=,\n user="", settings={"use_numpy": True}) as client:\n # insert entire pandas dataframe\n client.insert_dataframe(\n \'INSERT INTO test_table VALUES\',\n df.loc[mask1])\n client.insert_dataframe(\n \'INSERT INTO test_table (* EXCEPT(day)) VALUES\',\n df.loc[mask3].drop([\'day\'], axis=1))\nRun Code Online (Sandbox Code Playgroud)\n总结来说,我想问两件事:
\nDataTime?当空字符串插入到列中时,它会忽略默认值并使用 clickhouse 自己的默认值。在我看来,第二个可能是解决这个问题的关键,因为当我使用clickhouse-driver的客户端时,它可能会将NaT/NaN/None转换为空字符串。
\n编辑:\n对于问题2,我发现在clickhouse中,DateTime列会将空字符串视为 0(零)或 \'0\'(字符串中的零),这可以解释为什么 day 的值为 1970-01- 01 00:00:00.000。
所以,问题是:为什么 DateTime 会这样对待这个值?而且,我猜想 clickhouse-driver 客户端会将None/NaT/NaN 视为空字符串并将空字符串传递给 clickhouse。驱动程序是否可以将 None/NaT/NaN 视为 null(尽管,python 中只有 NoneType)或者只是删除单元格(例如,传递每一行,但我阅读了 clickhouse-driver 的代码发现它传递了每一列以获得完整的值)。
\n| 归档时间: |
|
| 查看次数: |
2603 次 |
| 最近记录: |