我正在学习 - Python,Pandas,SQL&深度学习。我想建立一个包含深度学习实验数据的数据库(使用Keras和Tensorflow)。源数据在8个CSV文件中约为10GB(总计)外汇时间戳的买入/卖出数据,源信息编码为三个3-4个char字符串,分类为Contributor,Region和City。
我可以通过pyodbc和sqlAlchemy连接到我的(空)MSSQL数据库;我可以将我的CSV文件读入数据帧;我可以在dB中创建一个简单的表,甚至可以从一个简单的数据帧创建一个表;我可以将日期和时间字段转换为自我想要的纪元以来的毫秒数。 (而且,FWIW,我已经实现了一个工作玩具LSTM模型以适应价格数据,我也有一些我在Mathematica中编写和编译的分析函数;我要么用Python调用C,要么让Mathematica工作直接在数据库上。)
问题是将CSV数据放入数据库。由于每个类别中只有十几个不同的来源,我认为我应该将贡献者等放入单独的表格中,例如,使用例如Contributor_ID作为整数(?),以便紧凑地存储数据,例如SELECT ... WHERE Region =“SHRUBBERY”是有效的。 (AFAICT我绝对不应该使用枚举,因为我可能会在以后获得更多的来源和类别。)
我的问题是 - 假设上述高度无知! - 我怎么能/应该a)使用python创建表和关系,然后b)填充这些表?
可选附加:为了节省空间,CSV文件省略了行和值与上面行相同的区域和城市 - 读取CSV以仅收集源信息(每个类别大约需要50秒)我知道如何重复删除和删除,但是当我想填充dB时,我怎样才能最有效地用前一行的值替换na?一个简单的For循环可以做到,但是例如某种方式“传播”列中的最后一个“真实”值以使用pandas替换na?
CSV示例:
Date Time Bid Price Ask Price Contributor Region City
04/02/2017 00:00.1 1.00266 1.00282 DCFX ASI AKL
04/02/2017 00:00.1 1.00263 1.0028 DCFX
04/02/2017 00:00.2 1.00224 1.00285 FXN NAM NYC
04/02/2017 00:00.2 1.00223 1.00288 FXN
感激地收到所有输入:)
答案 0 :(得分:0)
关系数据库(RDBMS)旨在将数据存储到具有主键/外键系统的相关逻辑分组中以规范化存储,其中除了其他优点之外还保持参考完整性(即,没有孤立记录)并且避免重复存储的数据。根据您的具体情况,请考虑以下事项:
数据库设计:了解数据片段的工作流程或“故事”(例如,数据输入中的第一个/后一个)并构建必要的表格模式。 Classic Database 101示例是Customers-Products-Orders,其中许多客户可以购买多个产品来填充许多订单(1对多和多对多关系),其中父表的主键是子表的外键。因此,请从此SO answer开始,如下所示构建模式布局。
根据您的需求,您的架构可能涉及贡献者,区域,城市,市场,公司(股票代码)和价格。此步骤将使用DDL命令(CREATE TABLE
,CREATE INDEX
,CREATE SCHEMA
),这些命令可以在pyodbc
游标或sqlAlchemy
引擎调用中运行,足以满足连接要求用户拥有此类权限。
但通常情况下,数据库设计命令在专门的管理控制台/ IDE或命令行工具中运行,而不是像Python这样的应用层代码,如SQL Server的Management Studio或sqlcmd;同样,Oracle的SQL Developer / sqlplus,MySQL的Workbench / cli或PostgreSQL的PgAdmin / psql。以下是价格表的设置示例:
# INITIALIZE SQLALCHEMY ENGINE
connection_string = 'mssql+pyodbc://{}:{}@{}/{}'\
.format(db_user,db_password,db_server,db_database)
engine = create_engine(connection_string)
sql = """
CREATE TABLE Prices (
ID INT IDENTITY(1,1) PRIMARY KEY,
DateTime DATETIME,
BidPrice DOUBLE(10,4),
AskPrice DOUBLE(10,4),
ContributorID INT,
RegionID INT,
CityID INT,
CONSTRAINT FK_Contributor FOREIGN KEY (ContributorID) REFERENCES Contributors (ID),
CONSTRAINT FK_Region FOREIGN KEY (RegionID) REFERENCES Regions (ID),
CONSTRAINT FK_City FOREIGN KEY (CityID) REFERENCES Cities (ID)
)
"""
# SQL ACTION QUERY VIA TRANSACTION
with engine.begin() as conn:
conn.execute(sql)
数据填充:由于数据集/数据集,csv或电子表格不等同于规范化的RDBMS表,但实际上是多个表的查询,因此迁移这些源将需要一些SQL争吵以与您的上述架构保持一致。将数据帧简单上载到SQL Server表中将导致低效且重复的存储。因此,请考虑以下步骤:
临时表(使用to_sql
)
使用临时表,临时表,这些表是来自pandas的原始转储。对于NAs问题,请使用DataFrame or Series前向填充ffill
来填充上述行中的NAs。
# FILL IN NAs IN ALL COLUMNS FROM PREVIOUS ROW
df = df.ffill() # OR df.fillna(method='ffill')
# FILL IN NAs FOR SPECIFIC COLUMNS
df['Region'] = df['Region'].ffill()
df['City'] = df['City'].ffill()
# DUMP DATA INTO DATA FRAME
df.to_sql(name='pandas_prices_dump', con=engine, if_exists='replace', index=False)
迁移到最终表(按字符串名称连接查找表)
然后,运行操作查询(即DML命令:INSERT INTO
,UPDATE
,DELETE
),以便从登台临时表中填充最终表。
sql = """
INSERT INTO Prices (Datetime, BidPrice, AskPrice,
ContributorID, RegionID, CityID)
SELECT pd.Datetime, pd.BidPrice, pd.AskPrice, c.ID, r.ID, cy.ID
FROM pandas_prices_dump pd
INNER JOIN Contributors c
ON c.ContributorName = pd.Contributor
INNER JOIN Regions r
ON r.RegionName = pd.Region
INNER JOIN Cities cy
ON cy.CityName = pd.City
"""
# APPEND FINAL DATA
with engine.begin() as conn:
conn.execute(sql)
# DROP STAGING TABLE
with engine.begin() as conn:
conn.execute("DROP TABLE pandas_prices_dump")
测试/检查最终表(使用read_sql
,按ID加入查找表)
# IMPORT INTO PANDAS (EQUIVALENT TO ORIGINAL df)
sql = """
SELECT p.Datetime, p.BidPrice, p.AskPrice,
c.ContributorName As Contributor, r.RegionName As Region,
cy.CityName As City
FROM Prices p
INNER JOIN Contributors c
ON c.ID = pd.ContributorID
INNER JOIN Regions r
ON r.ID = pd.RegionID
INNER JOIN Cities cy
ON cy.ID = pd.CityID
"""
prices_data = pd.read_sql(sql, engine)