学习笔记

pandas批量读取与合并csv文件的内容并导出、操作HDF文件、resample()转换数据周期、groupby()数据分组

print('--------------批量读取与合并csv文件的内容并导出-------------------')
import os
import pandas as pd
file_location='F:/gp'   #读取的文件夹
file_list=[]    #新建一个列表用于存放将所有的csv文件的路径放入列表
for root,dir,files in os.walk(file_location):   #当前文件夹路径、当前文件夹包含的文件夹、当前文件夹包含的文件
    for filename in files:  #遍历所有的文件
        if filename.endswith('.csv'):   #如果文件名以.csv结尾
            file_path=os.path.join(root,filename)   #文件路径=当前文件夹路径与文件名的连接
            file_path=os.path.abpath(file_path)
            #file_list.append(file_path) #将文件路径放入之前创建的用于存放所有文件路径的列表中
            file_list.append([filename,file_path])  #将文件名与其对应的文件路径做成一个列表,放入file_list列表

print(file_list)    #输出存放所有csv文件的路径 的列表

all_data=pd.DataFrame() #创建一个数据表

print('-----------------')
for fp in sorted(file_list)[:10]:   #遍历file_list列表对象的文件,后面的切片操作表示只取列表中前10个文件
    df=pd.read_csv(fp,skiprows=1,encoding='gbk')    #读取文件,跳过第一行,gbk编码,读取数据存入df对象
    #all_data=all_data.append(df,ignore_index=True) #功能是将df对象存入all_data数据表中,但pandas提示该方法已过时
    all_data=pd.concat([all_data,df])   #使用pandas的concat方法,将前面的all_data数据表与新读取的单文件数据表相连接,返回给all_data数据表

print(all_data)
all_data.to_csv('尝试concat.csv',index=False,encoding='gbk')  #将all_data大数据表导出成csv,省略index,gbk编码

all_data.to_hdf('尝试concat.hdf',key='all_data',mode='a') #将all_data导出成hdf,key类似于Excel工作簿中的工作表
#all_data.to_hdf('output233.hdf',key='all_data',mode='w')


print('-----------读取HDF文件---------------------')
hdf=pd.read_hdf('尝试concat.hdf',key='all_data')  #读取hdf
print(hdf)

print('-----------------------操作HDF文件----------------------------------')

import pandas as pd
import os

pd.set_option('expand_frame_repr', False)  # 当列太多时显示完整

file_location='f:/gp'
file_list=[]

for root,dir,files in os.walk(file_location):
    for filename in files:
        if filename.endswith('.csv'):
            file_path=os.path.join(root,filename)
            file_path=os.path.abspath(file_path)
            file_list.append([filename,file_path])  #将文件名与文件对应的路径,生成一个列表,让如file_list列表


#print(file_list)

#创建hdf文件
hdf=pd.HDFStore('hdf文件.hdf',mode='w')
#exit()

for filename,file_path in sorted(file_list)[:100]:   #遍历file_list列表中的filename与file_path,取前10个
    stock_code=filename.split('.')[0]   #读取文件名,然后用.分割,得到字符.前面的股票代码
    print(stock_code,filename,file_path)    #输出了股票代码,对应的文件名,对应的文件路径
    df=pd.read_csv(file_path,encoding='gbk',skiprows=1,parse_dates=['交易日期'])
    # 存储数据到hdf
    hdf[stock_code]=df.iloc[:100]   #每个文件只读取前100行
#exit()

#关闭hdf文件
hdf.close()


#读取hdf文件
hdf=pd.HDFStore('hdf文件.hdf',mode='r')

#获取hdf文件中的所有key
print(hdf.keys())

#读读取hdf文件中指定key的内容(两种方法)
print(hdf.get('sh600007'))
#或者
print(hdf['sh600006'])

#关闭hdf文件
hdf.close()

# 读取某个key指向的数据
# print(h5_store.get('sh600000'))
# print(h5_store['sh600000'])




# =====将数据存入hdf文件
# 批量读取文件名称
# file_list = []
# # 存储csv文件的文件夹路径
# file_location = r'C:\Users\Simons\Desktop\xbx_stock_2019\data\basic-trading-data\stock_data'
#
# for root, dirs, files in os.walk(file_location):
#     for filename in files:
#         if filename.endswith('.csv'):
#             file_path = os.path.join(root, filename)
#             file_path = os.path.abspath(file_path)
#             file_list.append([filename, file_path])
#
# # 创建hdf文件
# h5_store = pd.HDFStore('a_stock_100.h5', mode='w')
#
# # 批量导入并且存储数据
# for filename, file_path in sorted(file_list)[:300]:
#     stock_code = filename.split('.')[0]
#     print(stock_code, filename, file_path)
#     df = pd.read_csv(file_path, encoding='gbk', skiprows=1, parse_dates=['交易日期'])
#
#     # 存储数据到hdf
#     h5_store[stock_code] = df.iloc[:100]
#
# # 关闭hdf文件
# h5_store.close()
# exit()

# =====读取hdf数据
# 创建hdf文件
# h5_store = pd.HDFStore('a_stock_100.h5', mode='r')

# h5_store中的key
# print(h5_store.keys())

# 读取某个key指向的数据
# print(h5_store.get('sh600000'))
# print(h5_store['sh600000'])

# 关闭hdf文件
# h5_store.close()
print('------------------resample()转换数据周期--------------------------')

import pandas as pd

print('------------------将日线数据转换为周线数据--------------------------')


pd.set_option('expand_frame_repr', False)  # 当列太多时显示完整

# === 从hdf中读取1分钟数据
'''df: pd.DataFrame = pd.read_hdf('a_stock_100.h5', key='sh600000')
print(df.head(20))'''

df:pd.DataFrame=pd.read_hdf('hdf文件.hdf',key='sh600006')



#将交易日期列设置为index
df.set_index('交易日期',inplace=True)
print(df)


rule_type='1w'  #1w表示1周
period_df=df[['收盘价']].resample(rule=rule_type).last()   #1周为1组,取df数据表的收盘价列的1组的最后一个值
#resample()函数用于数据聚合,rule已在之前设置为1周,.last()表示取最后一个值

'''
1999-08-01  6.74    #然而1999年8月1日是星期日
1999-08-08  6.98
...'''

period_df['开盘价']=df['开盘价'].resample(rule=rule_type).first()
period_df['最高价']=df['最高价'].resample(rule=rule_type).max()
period_df['最低价']=df['最低价'].resample(rule=rule_type).min()
period_df['成交量']=df['成交量'].resample(rule=rule_type).sum()

print(period_df)
'''
             收盘价   开盘价   最高价   最低价          成交量
交易日期                                           
1999-08-01  6.74  7.27  7.31  6.63  160821400.0
1999-08-08  6.98  6.74  7.07  6.63   53723500.0
...'''


print('-------------更加精简的日线转换周线的写法-------------------')
'''输出结果的交易日期这一列与上一个写法有所不同,如果lebel='right'则与上一种写法的结果相同,推荐left'''

'''在index不是日期的情况下,需要设置on参数,on='交易日期',已设置日期index则不需要on
python中的agg函数通常用于调用groupby()函数之后,对数据做一些聚合操作,包括sum,min,max以及其他一些聚合函数

base残水对1天以上的周期没有效果,主要用于分钟与小时级别的计算'''
period_df2=df.resample(rule=rule_type,base=0,label='left').agg(
{
    #对哪些列分别进行哪些操纵
    '开盘价':'first',
    '最高价':'max',
    '最低价':'min',
    '收盘价':'last',
    '成交量':'sum',
})

print('-------------------------数据清理-----------------------')
'''当某个周期没有数据,会返回NaN值而不是跳过'''
#去除一天都没有交易的周
period_df2.dropna(subset='开盘价',inplace=Truue)
#去处成交量为0的交易周期
period_df2=period_df2[period_df2['成交量']>0]


# ===rule的取值
"""
    B       business day frequency
    C       custom business day frequency (experimental)
    D       calendar day frequency
    W       weekly frequency
    M       month end frequency
    SM      semi-month end frequency (15th and end of month)
    BM      business month end frequency
    CBM     custom business month end frequency
    MS      month start frequency
    SMS     semi-month start frequency (1st and 15th)
    BMS     business month start frequency
    CBMS    custom business month start frequency
    Q       quarter end frequency
    BQ      business quarter endfrequency
    QS      quarter start frequency
    BQS     business quarter start frequency
    A       year end frequency
    BA      business year end frequency
    AS      year start frequency
    BAS     business year start frequency
    BH      business hour frequency
    H       hourly frequency
    T       minutely frequency
    S       secondly frequency
    L       milliseonds
    U       microseconds
    N       nanoseconds
"""
print('-------------------groupby()数据分组---------------------------------')

import pandas as pd

pd.set_option('expand_frame_repr', False)  # 当列太多时显示完整

# =====导入数据
df = pd.read_csv(
    r'G:\教程\量化邢不行2019\00股票量化配套课件\xbx_stock_2019_0420\data\a_stock_201903.csv',
    encoding='gbk',

)
print(df)

print('-------------------pandas的groupby()-----------------')
'''groupby()可以根据指定列标签中的相同内容进行数据分组,并且将此列标签设置为group的index,如果不设置index,可以加入参数如as_index=False
groupby('列标签').size()可以统计该列标签下,按照相同内容分组,每一组有多少行'''

print(df.groupby('股票名称').size())    #统计数据表中每只股票的交易日期有多少天
'''
股票名称
*ST东凌    21
*ST东南    21
*ST东电    21
...'''

print(df.groupby('交易日期').size())    #可以统计每天有多少只股票在交易
'''
交易日期
2019-03-01    3573
2019-03-04    3573
2019-03-05    3571
...'''


print('--------------获取指定分组中的内容--------------------')
print(df.groupby('交易日期').get_group('2019-03-01'))
'''
           股票代码  股票名称        交易日期     开盘价     最高价     最低价     收盘价    前收盘价         成交量           成交额
0      sh600000  浦发银行  2019-03-01   11.81   12.06   11.60   12.02   11.74  63254621.0  7.477533e+08
21     sh600004  白云机场  2019-03-01   12.44   13.17   12.36   13.15   12.32  29721436.0  3.805480e+08
42     sh600006  东风汽车  2019-03-01    4.36    4.41    4.26    4.35    4.36  16291473.0  7.020395e+07
63     sh600007  中国国贸  2019-03-01   14.48   14.53   14.30   14.47   14.42   1763100.0  2.540480e+07
84     sh600008  首创股份  2019-03-01    4.06    4.06    3.97    4.02    4.00  33963007.0  1.359907e+08
...         ...   ...         ...     ...     ...     ...     ...     ...         ...           ...
74826  sz300757  罗博特科  2019-03-01   68.52   69.79   67.50   68.40   67.89   3241733.0  2.222516e+08
74847  sz300758  七彩化学  2019-03-01   51.23   51.23   51.23   51.23   46.57    172612.0  8.842912e+06
74868  sz300759  康龙化成  2019-03-01   40.20   42.38   39.43   41.14   38.80  28050195.0  1.137005e+09
74889  sz300760  迈瑞医疗  2019-03-01  129.00  131.00  124.81  128.39  127.30   5811638.0  7.446308e+08
74910  sz300761  立华股份  2019-03-01   80.00   85.89   80.00   85.89   78.08  15485401.0  1.284312e+09

[3573 rows x 10 columns]'''


print('---')
print(df.groupby('股票名称').get_group('七彩化学'))
'''
           股票代码  股票名称        交易日期    开盘价    最高价    最低价    收盘价   前收盘价         成交量          成交额
74847  sz300758  七彩化学  2019-03-01  51.23  51.23  51.23  51.23  46.57    172612.0    8842912.0
74848  sz300758  七彩化学  2019-03-04  56.35  56.35  54.00  56.35  51.23  15612750.0  864320760.0
74849  sz300758  七彩化学  2019-03-05  55.20  58.55  55.00  57.50  56.35  13792252.0  781378033.0
74850  sz300758  七彩化学  2019-03-06  56.00  58.49  55.55  57.39  57.50  11176049.0  635240244.0
74851  sz300758  七彩化学  2019-03-07  56.60  62.19  55.74  59.25  57.39  14074697.0  825992350.0
74852  sz300758  七彩化学  2019-03-08  56.24  57.02  53.33  53.33  59.25   9787522.0  540877041.0
74853  sz300758  七彩化学  2019-03-11  52.11  54.40  52.11  54.36  53.33   5808904.0  311076739.0'''


print('----------------groupby的常见功能--------------------------')
'''df.groupby('列标签').describe() 
按照指定列标签进行分组,返回每一组数据的每一个列标签的count       mean        std    min    25%    50%      75%    max信息

df.groupby('股票代码').head(行数))  返回按照指定列标签分组后,每组的前指定的行数的行
df.groupby('列标签').tail(行数)  #返回每一组的指定的后几行

df.groupby('列标签').first()   #返回每一组的第一行
df.groupby('列标签').last()    返回每一组的最后一行

df.groupby('列标签').nth(第几行) 返回指定的第几行


'''
#print(df.groupby('股票代码').describe())
print(df.groupby('股票代码').head(3))   #返回每一组的前3行






print('--------------分组后仅取指定的其他列用于计算-----------------------')
print(df.groupby('股票名称' ,as_index=False)['收盘价','成交量'].mean())    #计算每组指定列标签的平均值
'''
FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead.'''
'''
       股票名称        收盘价           成交量
0     *ST东凌   5.246667  6.050663e+06
1     *ST东南   2.040952  5.186515e+07
...'''

print(df.groupby('股票名称' ,as_index=False)['收盘价','成交量'].sum())




print('---------计算当前行指定的列数据在分组中的排名-----------')
'''计算每一行 在该分组中按照指定列标签排序的排名,如果要以百分比显示,则在rank参数中加入pct=True'''
print(df.groupby('股票名称',as_index=False)['收盘价'].rank())


# print(df.groupby('股票代码').describe())  # 只会对数值变量进行describe
# print(df.groupby('股票代码').head(3))
# print(df.groupby('股票代码').tail(3))  # 每个group里面的行顺序,会保留。
# print(df.groupby('股票代码').first())
# print(df.groupby('股票代码').last())
# print(df.groupby('股票代码').nth(2))
# 将group变量不设置为index
# print(df.groupby('股票代码', as_index=False).nth(2))



# ===== groupby常用操作汇总
# 根据'交易日期'进行group,将相同'交易日期'的行放入一个group,
# print(df.groupby('交易日期'))  # 生成一个group对象。不会做实质性操作,只是会判断是否可以根据该变量进行groupby

# group后可以使用相关函数,size()计算每个group的行数
# print(df.groupby('交易日期').size())  # 每天交易的股票数目
# 根据'股票代码'进行group,将相同'股票代码'的行放入一个group,
# print(df.groupby('股票代码').size())  # 每个股票交易的天数


# 获取其中某一个group
# print(df.groupby('交易日期').get_group('2019-03-25'))
# print(df.groupby('股票代码').get_group('sh600000'))


# 其他常见函数
# print(df.groupby('股票代码').describe())  # 只会对数值变量进行describe
# print(df.groupby('股票代码').head(3))
# print(df.groupby('股票代码').tail(3))  # 每个group里面的行顺序,会保留。
# print(df.groupby('股票代码').first())
# print(df.groupby('股票代码').last())
# print(df.groupby('股票代码').nth(2))
# 将group变量不设置为index
# print(df.groupby('股票代码', as_index=False).nth(2))


# 在group之后,取一部分变量进行计算
# 计算每个group的均值
# print(df.groupby('股票代码')['收盘价', '成交量'].mean())
# 计算每个group的最大值
# print(df.groupby('股票代码')['收盘价', '成交量'].max())

# 计算每个group的加总
# print(df.groupby('股票代码')['成交量'].sum())

# 计算该数据在每个group中的排名
# print(df.groupby('交易日期')['成交量'].rank())
# print(df.groupby('交易日期')['成交量'].rank(pct=True))


# 也可以同时用多个变量来进行group,将这些变量的值都相同的行
# df['交易日期'] = pd.to_datetime(df['交易日期'])
# df.loc[df['交易日期'].dt.day < 15, '月份'] = '上旬'
# df['月份'].fillna(value='下旬', inplace=True)
# print(df)

# print(df.groupby(['股票代码', '月份']).size())


# 我们之前讲过的resample、fillna、apply等常见操作,在group里面都可以进行。
# 这些操作需要大家有一定的积累,若直接在group上进行这些操作不熟练,可以使用已下的方式。


# 遍历group,对每个group进行单独操作,然后将这些group合并起来。
# 语法:for key, group in df.groupby('列名'):

# for code, group in df.groupby('股票代码'):
#     print(code)
#     print(group)

# 以下可以对各个group进行任意操作。
# group.fillna()
# group.apply()

# 操作完之后,将这些group再append起来

# 在一开始不熟练的时候,可以多用遍历每个group的方式

发表回复