簡體   English   中英

如何使用 Python/Pandas for-loop 在 for-loop 中讀取帶有查詢參數的 SQLite 文件?

[英]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表中的所需值。

解決方案 1

此解決方案使用與原始帖子中暗示的方法類似的方法,利用 Python F 字符串batch中的值注入用於填充data的每個查詢中。

data = [pd.read_sql(f"""SELECT ID,Time,A,B FROM Main WHERE BatchID='{b}'""", conn) for b in batch]

解決方案 2

此解決方案僅查詢數據庫一次,從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM