在现有的sql表中创建新列,其中包含来自pandas Dataframe的额外列

时间:2016-07-24 05:15:05

标签: python sqlite sqlalchemy

我有几个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中的列名?

1 个答案:

答案 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)