我有几个pandas Dataframe
我希望写入SQL database
。但是,由于现有SQL database
可能没有column name
中的特定pandas Dataframe
,因此我收到一条错误消息,指出the column in the table was not found, thus unable to append data
。
# Example:
df1
out= column1, column2, column3, column4
value1, value2, value3, value4
df2
out= columnA, columnB, columnC
valueA, valueB, valueC
# Initially I concat the df together and save it into SQL
combined_data = pandas.concat([df1, df2], axis=1,
join='inner')
pandas.DataFrame.to_sql(combined_data, name='table1', con=engine,
if_exists='append', index=False)
但是,因为已经使用所有列创建了此表,如果df2要包含其他列,则会收到错误消息。
df2
out= columnA, columnB, columnC, columnD, columnE, columnF
valueA, valueB, valueC, valueD, valueE, valueF
如何构建代码,在现有SQL table
中使用这些列的名称创建新列,作为pandas Dataframe
中缺少的列名?
我想我可以使用以下sql code
connection.execute("ALTER TABLE table1 ADD COLUMN new_column INTEGER DEFAULT 0")
但是,如何确保添加的new_column
遵循df2中的列名?
答案 0 :(得分:1)
我遇到了类似的问题并采取了以下方法:
1)从数据库表中获取列的列表。这可以通过多种方式完成,但我使用的是postgres而不是sqllite。有关从postgresql获取表的列名,请参阅this SE问题。 This问题似乎回答了如何为sqlite做这件事。
db_columns = list(engine.execute("SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'my_table'"))
这会返回一个元组列表,所以得到每个元组的第一个元素:
db_columns = [x[0] for x in db_columns]
您可以将表加载到pandas中,然后使用数据框的列。这显然会占用更多资源:
db_columns = pd.read_sql_query("SELECT * FROM my_table", connection).columns
2)获取数据库表的列和df列之间的差异。我喜欢使用套装,因为我觉得它们很直观。但是他们没有保留顺序:
new_columns = set(df1.columns) - set(db_columns)
如果订单很重要,那么您可以使用过滤器:
new_columns = list(filter(lambda x: x not in db_columns, df1.columns))
3)迭代新列并准备将它们添加到表中:
query = ''
query params = []
for column in new_columns:
query+= "ALTER TABLE %s ADD COLUMN %s %s;"
query_params.extend(["my_table", column,"text"])
在此示例中,我使用了“text”,但您可能希望将其替换为与pandas / numpy dtype对应的原始数据类型。 np.asscalar(value)
是将numpy类型转换为python类型的一种方法。有关将numpy转换为python类型的更多信息,请参阅this SO问题。
最后将所有列添加到表中:
result = connection.execute(query, query_params)