2016-09-28 42 views
2

我遍歷數據庫中的表和日期列表以收集數據。這樣的事情:將for循環調整爲列表理解

df_list = [] 
for table in table_list: 
    for date in required_date_range: 
     query = 'SELECT * FROM {} WHERE row_date = {};'.format(table, date) 
     df = pd.read_sql_query(sql=query, con=engine) 
     df_list.append(df) 

result = pd.concat(df_list) 

有沒有辦法把這樣的循環放入列表理解?它甚至值得嗎?

我發現一些示例代碼https://tomaugspurger.github.io/modern-4-performance.html

files = glob.glob('weather/*.csv') 
weather_dfs = [pd.read_csv(fp, names=columns) for fp in files] 
weather = pd.concat(weather_dfs) 

它看起來更好,圖表顯示它的性能會更好,但我似乎無法環繞它我的頭,當我試着調整自己的代碼。

編輯 -

看來,如果我做了查詢的列表,而不是工作。有沒有辦法讓循環和.format初始化爲列表理解?

for table in table_list: 
    for date in required_date_range: 
     queries = ['SELECT * FROM {} WHERE row_date = {};'.format(table, date)] 

dfs = [pd.read_sql_query(query, con=pg_engine) for query in queries] 

回答

1

我認爲這應該工作

def q(table, date): 
    query = 'SELECT * FROM {} WHERE row_date = {};'.format 
    return pd.read_sql_query(sql=query(table, date), con=engine) 

df_list = [q(table, date) for table in table_list for date in required_date_range] 

Dmonstration
注:我切換到,因爲這是一個示範只返回查詢和我沒有你數據庫連接。

table_list = ['table1', 'table2'] 
required_date_range = ['date1', 'date2'] 

def q(table, date): 
    query = 'SELECT * FROM {} WHERE row_date = {};'.format 
    return query(table, date) 

df_list = [q(table, date) for table in table_list for date in required_date_range] 

df_list 

['SELECT * FROM table1 WHERE row_date = date1;', 
'SELECT * FROM table1 WHERE row_date = date2;', 
'SELECT * FROM table2 WHERE row_date = date1;', 
'SELECT * FROM table2 WHERE row_date = date2;'] 
+0

我沒有downvote任何東西。讓我試試這個。 – trench

3

我不認爲列表理解本身會給你顯着的性能提升。我的意思是,與循環相比,它可能會帶來輕微的性能提升,但我認爲這與其他需要完成的事情無關。查詢數據庫,初始化數據幀,進行分段。

什麼可能給你一個性能提升是通過使用SQL IN運營商消除你內心的循環:

SELECT * FROM table_name WHERE row_date IN (date1, date2, date3,...); 

所以,將你的循環更改爲類似:

df_list = [] 
for table in table_list: 
    query = 'SELECT * FROM {} WHERE row_date IN ({});'.format(table, ','.join(date_range)) 
    df = pd.read_sql_query(sql=query, con=engine) 
    df_list.append(df) 

從那麼將其轉換爲理解是相當直接的:

query = 'SELECT * FROM {} WHERE row_date IN ({});' 
dfs = (pd.read_sql_query(sql=query.format(table, ','.join(date_range)), con=engine) for table in table_list) 
df = pd.concat(dfs) 

如果從每個表中的列是相同的,以相同的順序,你甚至可以通過使用UNION ALL打造沿線的單個查詢消除表圈:

SELECT * FROM table1 WHERE row_date IN (date1, date2, date3,...) 
UNION ALL 
SELECT * FROM table2 WHERE row_date IN (date1, date2, date3,...) 
UNION ALL 
... 

然後就是做單read_sql_query電話:

df = pd.read_sql_query(sql=union_all_query, con=engine) 
+0

我沒有意識到IN語法會提高性能。我會立即執行,並測試你的列表理解。 – trench

+0

如果日期連續,使用'BETWEEN'可能會更好,即'WHERE row_date BETWEEN first_date AND last_date'。 – root