cd9*_*d98 5 python sqlite sqlalchemy pandas
我觉得我忽略了一些非常简单的事情,但我无法让它发挥作用。我现在正在使用SQLite
,但解决方案SQLAlchemy
也将非常有帮助。
让我们创建原始数据集:
### This is just the setup part
import pandas as pd
import sqlite3
conn = sqlite3.connect('test.sqlite')
orig = pd.DataFrame({'COLUPC': [100001, 100002, 100003, 100004],
'L5': ['ABC ALE', 'ABC MALT LIQUOR', 'ABITA AMBER', 'ABITA AMBER'],
'attr1': [0.25, 0.25, 0.041, 0.041]})
orig.to_sql("UPCs", conn, if_exists='replace', index=False)
#Create an index just in case it's needed
conn.execute("""CREATE INDEX upc_index
ON UPCs (COLUPC);""")
Run Code Online (Sandbox Code Playgroud)
现在假设我接受orig
dataframe
并添加一个名为“L5_lower”的列。然后我在 SQLite 数据库中创建列:
# Create new variable
orig['L5_lower'] = orig.L5.str.lower()
conn.execute("alter table UPCs add column L5_lower TEXT;")
Run Code Online (Sandbox Code Playgroud)
现在假设我想将这一列填充L5_lower
到 SQLite 表中,而不必传递其他列(下面我解释为什么我需要这个)
我尝试将索引和新列作为元组传递:
query='''insert or replace into UPCs (COLUPC, L5_lower) values (?,?) '''
conn.executemany(query, orig[['COLUPC', 'L5_lower']].to_records(index=False))
conn.commit()
# But then:
df = pd.read_sql("SELECT * FROM UPCs;", conn)
conn.close()
Run Code Online (Sandbox Code Playgroud)
给出了这个混乱的结果。
COLUPC L5 attr1 L5_lower
0 100001 ABC ALE 0.250 None
1 100002 ABC MALT LIQUOR 0.250 None
2 100003 ABITA AMBER 0.041 None
3 100004 ABITA AMBER 0.041 None
4 b'\xa1\x86\x01\x00\x00\x00\x00\x00' None NaN abc ale
5 b'\xa2\x86\x01\x00\x00\x00\x00\x00' None NaN abc malt liquor
6 b'\xa3\x86\x01\x00\x00\x00\x00\x00' None NaN abita amber
7 b'\xa4\x86\x01\x00\x00\x00\x00\x00' None NaN abita amber
Run Code Online (Sandbox Code Playgroud)
相反,预期的输出是:
COLUPC L5 attr1 L5_lower
0 100001 ABC ALE 0.250 abc ale
1 100002 ABC MALT LIQUOR 0.250 abc malt liquor
2 100003 ABITA AMBER 0.041 abita amber
3 100004 ABITA AMBER 0.041 abita amber
Run Code Online (Sandbox Code Playgroud)
那么,为什么我要尝试传递单列?我有一个非常大的数据集,我将无法在内存中保存整个数据框。我的预期工作流程是一次构造一列,然后update
或insert
进入 SQLite 数据库。
据我所知,您无法使用 Pandas to_sql 添加列 - 您可以添加行。一种解决方案是将新列插入临时表(具有与原始表相同的索引),然后在 SQLite 端更新源表。
这是一个工作示例:
设置:
假设我们有以下原始 DF:
In [79]: orig
Out[79]:
COLUPC L5 attr1
0 100001 ABC ALE 0.250
1 100002 ABC MALT LIQUOR 0.250
2 100003 ABITA AMBER 0.041
3 100004 ABITA AMBER 0.041
In [80]: orig.set_index('COLUPC', inplace=True)
In [81]: conn = sqlite3.connect('d:/temp/test.sqlite')
In [82]: orig.to_sql('upcs', conn, if_exists='replace', index=True)
In [83]: conn.close()
Run Code Online (Sandbox Code Playgroud)
解决方案:
In [84]: conn = sqlite3.connect('d:/temp/test.sqlite')
In [85]: df = pd.read_sql('select * from upcs', conn, index_col='COLUPC')
In [86]: df
Out[86]:
L5 attr1
COLUPC
100001 ABC ALE 0.250
100002 ABC MALT LIQUOR 0.250
100003 ABITA AMBER 0.041
100004 ABITA AMBER 0.041
Run Code Online (Sandbox Code Playgroud)
创建临时表:
In [87]: tmp = orig.L5.str.lower().to_frame('L5_lower')
In [88]: tmp
Out[88]:
L5_lower
COLUPC
100001 abc ale
100002 abc malt liquor
100003 abita amber
100004 abita amber
In [89]: tmp.to_sql('tmp', conn, if_exists='replace', index=True)
Run Code Online (Sandbox Code Playgroud)
向 SQLite 表添加新列:
In [90]: conn.execute('alter table UPCs add column L5_lower varchar(50)')
Out[90]: <sqlite3.Cursor at 0xa558c00>
In [91]: qry = 'update upcs set L5_lower = (select L5_lower from tmp where tmp.COLUPC = upcs.COLUPC) where L5_lower is NULL'
In [92]: conn.execute(qry)
Out[92]: <sqlite3.Cursor at 0xa593570>
In [93]: conn.commit()
In [94]: conn.execute('drop table tmp')
Out[94]: <sqlite3.Cursor at 0xa5930a0>
Run Code Online (Sandbox Code Playgroud)
查看:
In [95]: pd.read_sql('select * from upcs', conn, index_col='COLUPC')
Out[95]:
L5 attr1 L5_lower
COLUPC
100001 ABC ALE 0.250 abc ale
100002 ABC MALT LIQUOR 0.250 abc malt liquor
100003 ABITA AMBER 0.041 abita amber
100004 ABITA AMBER 0.041 abita amber
In [96]: conn.close()
Run Code Online (Sandbox Code Playgroud)