标题有点太抽象了,其实是因为我最近遇上两个需求:
一个是将一些以1min为单位的时间序列存储成blob类型存入mysql(压缩),并且以序号和日期为主键。同时写一个api将其读取并还原(扩展)
二个是写一个api,输入为有效期范围(startDate和EndDate)和序号(stock_code),输出为每个序号在有效期范围内(扩展),每日涉及到的内容(concept_code),其中内容以list返回(压缩),且序号和日期组成组件
先说第一部分:
压缩
all_index_info = [] # blob数据的容器
def get_all_index_data():
# 以序号和日期为主键,分组传参
all_index_minute_price.groupby(['index_code','trade_date'],as_index=False).apply(lambda x:data_to_string(x))
data = pd.DataFrame(all_index_info) # 转为DataFrame
def data_to_string(each_data):
index_info = {
}
index_info['index_code'] = normalize_code_dg(each_data['index_code'].tolist()[0])# 序号
index_info['trade_date'] = each_data['trade_date'].tolist()[0]# 日期
index_info['open_minute'] = np.array(each_data['open']).astype(np.float32).tostring()# 将数据转为字符串(即我说的压缩)
index_info['open_minute'] = np.array(each_data['open']).astype(np.float32).tostring()
index_info['high_minute'] = np.array(each_data['high']).astype(np.float32).tostring()
index_info['low_minute'] = np.array(each_data['low']).astype(np.float32).tostring()
index_info['turnover_share_minute'] = np.array(each_data['volume']).astype(np.float32).tostring()
index_info['turnover_value_minute'] = np.array(each_data['money']).astype(np.float32).tostring()
all_index_info.append(index_info)
扩展
def minutes_data_decoder(raw_data = pd.DataFrame()):
"""
Args:
raw_data: 带有分钟数据的dataframe
Returns:
df_result: decode之后的包含分钟数据的DataFrame
"""
data_index = raw_data.index.values.tolist() # 取出序号
raw_data = raw_data.reset_index(drop=True)# 删除索引
for data_column in raw_data.columns.values:
if data_column[-6:] == 'minute': #若为分钟数据
name_list = []
for i in range(1, 241): # open_minute_001,open_minute_002...
name_list.append(data_column + '_' + str(i).zfill(3))
tmp = pd.DataFrame([x.tolist() for x in raw_data[data_column].apply(_bytes_decode).values],
columns=name_list)
raw_data = pd.concat([raw_data, tmp], axis=1)# 横向扩展
raw_data = raw_data.drop(columns=[data_column])
data = raw_data.set_index(pd.Index(data_index))
data = data.rename_axis(['stock_code','trade_date'])
return data
##分钟数据转换为原始数据
def _bytes_decode(close_minute):
try:
close_minute = np.frombuffer(close_minute, dtype=np.float32)
except:
close_minute = np.array([])
return close_minute
第二部分:
原始数据是这样:
def deal(result,):
result.loc[pd.to_datetime(result['startDate'],format='%Y-%m-%d') < pd.to_datetime(trade_date_list[0][0],format='%Y-%m-%d'),'startDate'] = pd.to_datetime(trade_date_list[0][0],format='%Y-%m-%d')# 比较前先转换时间格式
result.loc[pd.to_datetime(result['endDate'],format='%Y-%m-%d') > pd.to_datetime(trade_date_list[-1][-1],format='%Y-%m-%d'),'endDate'] = pd.to_datetime(trade_date_list[-1][-1],format='%Y-%m-%d')
temp = result.apply(lambda x:pd.Series(pd.date_range(x['startDate'],x['endDate'])),axis=1).stack().reset_index(level=1) # 将生成的时间Series化后,用stack将列索引转为行索引后重设索引(扩展)
result = pd.concat([result,temp],axis=1).drop(['startDate','endDate','level_1'],axis=1).rename(columns={
0:'trade_date'}) #使用concat根据索引对齐
result = result.groupby(['stock_code','trade_date'],as_index=False).apply(lambda x:x['concept_code'].drop_duplicates().tolist()).reset_index().rename(columns={
0:'concept_code'}) #按“输入值+时间”分组,将组内代码去重后转化为list,再重设索引(压缩)
那如何还原呢?
# 将字符串类型的list(放入csv之后再读出来就变成字符串类型的list)转为list,再转为series
concept_code_series = data.apply(lambda x:pd.Series(eval(x['concept_code'])),axis=1)
# 将concept_code与index对齐
result = pd.concat([data[['stock_code','trade_date']],concept_code_series ])
# 列索引转行索引
result = result.stack()
# 取消索引
result = result.reset_index(level=0).rename(columns={
0:'concept_code'})