[英]How to with Python/Pandas for-loop read SQLite-file with query-parameter in the for-loop?
我想從 SQLite 數據庫中提取一些表。 這些表具有不同的行數,因此很自然地將它們存儲在 Python 列表中,以方便進一步的數據分析。 以下代碼有效。
import sqlite3
import pandas as pd
conn = sqlite3.connect("Database")
data = []
data.append(pd.read_sql("""SELECT ID,Time,A,B FROM Main WHERE BatchID=='BATCH1'""", conn))
data.append(pd.read_sql("""SELECT ID,Time,A,B FROM Main WHERE BatchID=='BATCH2'""", conn))
conn.close()
print(data[0]['Time'])
與其為每個 BatchID 重復代碼,不如使用 for 循環,例如
conn = sqlite3.connect("Database")
data = []
batch = ['BATCH1', 'BATCH2']
for k in list(range(2)):
data.append(pd.read_sql("""SELECT ID,Time,A,B FROM Main WHERE BatchID='eval(batch[k])'""", conn))
conn.close()
print(data[0]['Time'])
但這不起作用。 如果我嘗試使用這種技術只讀取一個表並顯式編寫 eval(batch[0]) ,那么我會得到一個只有鍵但沒有數據的表。
根據要求,我添加了一些上下文來說明為什么我有一個 DataFrames 列表。 我通常想要做的是輕松 plot 與 function 的圖表 A 如何隨不同批次的時間變化。 感興趣的批次集合可以是特定批次、或批次集合或全部。 plot 的代碼應該簡單透明。
for k in batches: ax1.plot(data[k]['Time'], data[k]['A'])
但是這個命令行可能很簡單,在 DataFrame 中使用選定變量的所有批次進行選擇。 我認為這里也是一個概念上的簡單性,我們有一個繪圖列表,我們使用上面的命令覆蓋在同一個圖中。
我也喜歡以類似的方式計算數據子集。
JPI93 下面建議的另一種方法是簡化第一步並制作一個大型 DataFrame,其中包含來自所有批次的數據以及所選變量。 這導致制作我認為所需的圖表的命令有點長。 代碼下方
...
data = pd.read_sql("""SELECT BatchID,ID,Time,A,B FROM Main""",conn)
index = []
index.append(data['BatchID'] == ' Batch1']
index.append(data['BatchID'] == ' Batch2']
batches = list(range(2))
然后我們可以使用以下命令 plot
for k in batches:ax1.plot(data.loc[index[k],'Time'],data.loc[index[k],'A'])
我傾向於支持上面的原始 plot 命令,但隨后我需要解決制作 DataFrames 列表的原始問題。 還是這里有一些其他方法可以使 plot 命令簡單易讀?
如果您使用的是 Python 3.6+,請嘗試格式化腳本:
conn = sqlite3.connect("Database")
data = []
batch = ['BATCH1', 'BATCH2']
for k in list(range(2)):
query = batch[k]
data.append(pd.read_sql(f"""SELECT ID,Time,A,B FROM Main WHERE BatchID='{query}'""", conn))
conn.close()
print(data[0]['Time'])
或者您可以使用舊式格式 function:
data.append(pd.read_sql(f"""SELECT ID,Time,A,B
FROM Main
WHERE BatchID='{}'""".format(query),
conn))
鑒於以下用於測試以下提供的解決方案的起始代碼:
import sqlite3
import pandas as pd
conn = sqlite3.connect(':memory:')
c = conn.cursor()
with conn:
c.execute('''
CREATE TABLE IF NOT EXISTS Main(
ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
Time TEXT NOT NULL,
A TEXT NOT NULL,
B TEXT NOT NULL,
BatchID TEXT NOT NULL);''')
c.execute('''
INSERT INTO Main (Time, A, B, BatchID) VALUES
('08:15:00', 'Atext1', 'Btext1', 'BATCH1'),
('08:30:00', 'Atext2', 'Btext2', 'BATCH2'),
('08:30:45', 'Atext3', 'Btext3', 'BATCH3'),
('25:15:50', 'Atext1.1', 'Btext1.1', 'BATCH1'),
('18:30:60', 'Atext2.1', 'Btext2.1', 'BATCH2'),
('00:04:45', 'Atext3.1', 'Btext3.1', 'BATCH3');''')
batch = ['BATCH1', 'BATCH2']
有幾種方法可以解決創建pandas.DataFrame
對象list
的問題,這些對象反映了由Main.BatchID
分隔的Main
表中的所需值。
此解決方案使用與原始帖子中暗示的方法類似的方法,利用 Python F 字符串將batch
中的值注入用於填充data
的每個查詢中。
data = [pd.read_sql(f"""SELECT ID,Time,A,B FROM Main WHERE BatchID='{b}'""", conn) for b in batch]
此解決方案僅查詢數據庫一次,從Main
返回所有值。 然后,它根據batch
值過濾生成的df
以根據需要填充data
。
df = pd.read_sql('SELECT ID, Time, A, B, BatchID FROM Main', conn)
data = [df[df['BatchID'] == b].iloc[:, df.columns != 'BatchID'] for b in batch] # New df for each BatchID in batches with BatchID column ommited in output as per OP
data = [d for d in data if d.shape[0] > 0] # Filter out any 0 row results if present (i.e. those where a value in batch is not present in Main.BatchID)
這個問題似乎很有可能實際上是一個XY Problem ,當然我可能會離開。
我這么認為的主要原因是,創建一個單獨的pandas.DataFrame
實例list
來從根本上解決過濾結果的問題似乎是多余的。 pandas
提供在單個pandas.DataFrame
上進行此類過濾的功能(如解決方案 2 中所示),以某種方式在以后的分析中可能更有效且更簡單。
在提交通過不同方法提出的問題的解決方案之前,可能值得查看有關選擇子集的文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.