我正在用Python做一些数据分析。我有约15,000种由ISIN代码标识的金融产品,以及每种产品的约15列每日数据。我想通过ISIN代码轻松快速地访问数据。
数据在MySQL数据库中。到目前为止,在Python方面,我一直在使用Pandas DataFrame。
我做的第一件事是使用pd.read_sql直接从数据库加载DF。但是,这相对较慢。然后,我尝试将完整的数据库加载到单个DF中并将其序列化为pickle文件。泡菜文件的加载很快,几秒钟。但是,当查询单个产品时,性能与我查询SQL DB的性能相同。这是一些代码:
import pandas as pd
from sqlalchemy import create_engine, engine
from src.Database import Database
import time
import src.bonds.database.BondDynamicDataETL as BondsETL
database_instance = Database(Database.get_db_instance_risk_analytics_prod())
engine = create_engine(
"mysql+pymysql://"
+ database_instance.get_db_user()
+ ":"
+ database_instance.get_db_pass()
+ "@"
+ database_instance.get_db_host()
+ "/"
+ database_instance.get_db_name()
)
con = engine.connect()
class DataBase:
def __init__(self):
print("made a DatBase instance")
def get_individual_bond_dynamic_data(self, isin):
return self.get_individual_bond_dynamic_data_from_db(isin, con)
@staticmethod
def get_individual_bond_dynamic_data_from_db(isin, connection):
df = pd.read_sql(
"SELECT * FROM BondDynamicDataClean WHERE isin = '"
+ isin
+ "' ORDER BY date ASC",
con=connection,
)
df.set_index("date", inplace=True)
return df
class PickleFile:
def __init__(self):
print("made a PickleFile instance")
df = pd.read_pickle("bonds_pickle.pickle")
# df.set_index(['isin', 'date'], inplace=True)
self.data = df
print("loaded file")
def get_individual_bond_dynamic_data(self, isin):
result = self.data.query("isin == '@isin'")
return result
fromPickle = PickleFile()
fromDB = DataBase()
isins = BondsETL.get_all_isins_with_dynamic_data_from_db(
connection=con,
table_name=database_instance.get_bonds_dynamic_data_clean_table_name(),
)
isins = isins[0:50]
start_pickle = time.time()
for i, isin in enumerate(isins):
x = fromPickle.get_individual_bond_dynamic_data(isin)
print("pickle: " + str(i))
stop_pickle = time.time()
for i, isin in enumerate(isins):
x = fromDB.get_individual_bond_dynamic_data(isin)
print("db: " + str(i))
stop_db = time.time()
pickle_t = stop_pickle - start_pickle
db_t = stop_db - stop_pickle
print("pickle: " + str(pickle_t))
print("db: " + str(db_t))
print("ratio: " + str(pickle_t / db_t))
这导致: 泡菜:7.636280059814453 分贝:6.167926073074341 比例:1.23806283819615
另外,奇怪的是,在DF上设置索引(取消注释构造函数中的行)会减慢一切!
我想尝试使用https://www.pytables.org/index.html替代熊猫。还有其他想法或意见吗?
问候, 乔治(Georgi)
答案 0 :(得分:0)
因此,整理一下评论中的一些想法:
mysqlclient
代替PyMySQL。isin
用于查询,date
用于排序)。index_col="date"
according to the docs中设置read_sql()
;可能会更快。self.data[self.data.isin == isin]
比self.data.query("isin == '@isin'")
的表现要好。答案 1 :(得分:0)
将大型数据帧转换为由ISIN代码索引的较小数据帧的字典{isin-> DF}很有帮助。与从DF相比,从字典中检索数据效率更高。同样,在给定ISIN代码的情况下,能够请求单个DF是很自然的。希望这对其他人有帮助。