pandas
以股票数据为例分析
一、基本使用
import pandas as pd
df = pd.read_csv(
filepath_or_buffer=r'文件路径',
encoding='gbk',
sep=',',
skiprows=1,
parse_dates=['交易日期'],
index_col=['交易日期'],
)
print(df)
print(df.shape)
print(df.shape[0])
print(df.columns)
print(df.index)
print(df.dtypes)
print(df.head(3))
print(df.tail(3))
print(df.sample(n=3))
print(df.describe())
pd.set_option('expand_frame_repr', False)
pd.set_option("display.max_rows", 1000)
pd.set_option('precision', 1)
print(df.head())
print(df['开盘价'])
print(df[['交易日期', '收盘价']])
print(df[['开盘价']])
print(df.loc[['1999-11-11', '1999-11-25']])
print(df.loc['1999-11-11'])
print(df.loc[['2000-03-30', '2000-07-31']])
print(df.loc['2000-03-30': '2000-04-30'])
print(df.loc[:, '开盘价':'最低价'])
print(df.loc['2000-03-30': '2000-07-31', '开盘价':'收盘价'])
print(df.loc[:, :])
print(df.at['2000-03-30', '开盘价'])
print(df.loc['2000-03-30', '开盘价'])
print(df.iloc[0])
print(df.iloc[1:3])
print(df.iloc[:, 1:3])
print(df.iloc[1:3, 1:3])
print(df.iloc[:, :])
print(df.iat[1, 3])
print(df['交易日期'] + ' 15:00:00')
print(df['收盘价'] * 100)
print(df[['收盘价', '成交量']])
print(df['收盘价'] * df['成交量'])
df['交易日期2'] = df['交易日期'] + ' 00:00:00'
print(df['交易日期2'])
df['交易所'] = '上交所'
print(df['收盘价'].mean())
print(df[['收盘价', '成交量']].mean())
print(df[['收盘价', '成交量']])
print(df[['收盘价', '成交量']].mean(axis=1))
axis = 1,
print(df['最高价'].max())
print(df['最低价'].min())
print(df['收盘价'].std())
print(df['收盘价'].count())
print(df['收盘价'].median())
print(df['收盘价'].quantile(0.25))
df['下周期收盘价'] = df['收盘价'].shift(-1)
del df['下周期收盘价']
df['涨跌'] = df['收盘价'].diff(1)
df.drop(['涨跌'], axis=1, inplace=True)
df['涨跌幅'] = df['收盘价'].pct_change(1)
df['累计成交量'] = df['成交量'].cumsum()
print(df[['交易日期', '成交量', '累计成交量','涨跌幅']])
print((df['涨跌幅'] + 1.0).cumprod())
df['收盘价_排名'] = df['收盘价'].rank(ascending=True, pct=False)
print(df[['收盘价', '收盘价_排名']])
del df['收盘价_排名']
print(df['收盘价'].value_counts())
print(df['股票代码'] == 'sh600000')
print(df[df['股票代码'] == 'sh600000'])
print(df[df['股票代码'] == 'sh600000'].index)
print(df[df['股票代码'].isin(['sh600000', 'sh600004', 'sz000001'])])
print(df[df['收盘价'] < 10.0])
print(df[(df['收盘价'] < 10.0) & (df['股票代码'] == 'AIDUSD')])
0.创建缺失值
index = df[df['交易日期'].isin(['2019-03-01', '2019-03-15'])].index
df.loc[index, '月头'] = df['交易日期']
1.删除缺失值
print(df.dropna(how='any'))
print(df.dropna(subset=['月头', '收盘价'], how='all'))
all代表全部为空,才会删除该行;any只要一个为空,就删除该行。
2.补全缺失值
print(df.fillna(value='N'))
df['月头'].fillna(value=df['收盘价'], inplace=True)
print(df.fillna(method='ffill'))
print(df.fillna(method='bfill'))
3.找出缺失值
print(df.notnull())
print(df[df['月头'].notnull()])
=====排序函数
print(df.sort_values(by=['交易日期'], ascending=1))
print(df.sort_values(by=['股票代码', '交易日期'], ascending=[1, 0]))
=====两个df上下合并操作,append操作
df1 = df.iloc[0:10][['交易日期', '股票代码', '收盘价', '成交量']]
print(df1)
df2 = df.iloc[5:15][['交易日期', '股票代码', '收盘价', '成交量']]
print(df2)
print(df1.append(df2))
df3 = df1.append(df2, ignore_index=True)
print(df3)
=====对数据进行去重
df3中有重复的行数,我们如何将重复的行数去除?
print(df3)
df3.drop_duplicates(
subset=['交易日期', '股票代码'],
keep='first',
inplace=True
)
print(df3)
=====其他常用重要函数
df.reset_index(inplace=True, drop=True)
df.rename(columns={
'收盘价': 'close',
'开盘价': 'open',
'股票代码': 'code',
'股票名称': 'name',
'交易日期': 'date',
'最高价': 'high',
'最低价': 'low',
'前收盘价': 'prev_close',
'成交量': 'volume',
'成交额': 'money'}, inplace=True)
print(df.empty)
print(pd.DataFrame().empty)
print(df.T)
=====字符串处理
print(df['股票代码'])
print('sh600000'[:2])
print(df['股票代码'].str[:2])
print(df['股票代码'].str.upper())
print(df['股票代码'].str.lower())
print(df['股票代码'].str.len())
df['股票代码'].str.strip()
print(df['股票代码'])
print(df['股票代码'].str.contains('767'))
print(df['股票代码'].str.replace('sz', 'sh'))
=====rolling、expanding操作
计算'收盘价'这一列的均值
print(df['收盘价'])
如何得到每一天的最近3天close的均值呢?即如何计算常用的移动平均线?
使用rolling函数
df['收盘价_3天均值'] = df['收盘价'].rolling(3).mean()
print(df[['收盘价', '收盘价_3天均值']])
rolling(n)即为取最近n行数据的意思,只计算这n行数据。后面可以接各类计算函数,例如max、min、std等
print(df['收盘价'].rolling(3).max())
print(df['收盘价'].rolling(3).min())
print(df['收盘价'].rolling(3).std())
rolling可以计算每天的最近3天的均值,如果想计算每天的从一开始至今的均值,应该如何计算?
使用expanding操作
df['收盘价_至今均值'] = df['收盘价'].expanding().mean()
print(df[['收盘价', '收盘价_至今均值']])
expanding即为取从头至今的数据。后面可以接各类计算函数
print(df['收盘价'].expanding().max())
print(df['收盘价'].expanding().min())
print(df['收盘价'].expanding().std())
rolling和expanding简直是为量化领域量身定制的方法,经常会用到。
=====输出到本地文件
print(df)
df.to_csv('output.csv', encoding='gbk', index=False)
二、进阶
import pandas as pd
import os
pd.set_option('expand_frame_repr', False)
df = pd.read_csv(
r'...\sh600004.csv',
encoding='gbk',
skiprows=1, parse_dates=['交易日期']
)
file_location = r'目标文件夹路径'
for root, dirs, files in os.walk(file_location):
print('当前文件夹:', root)
print('包含的文件夹:', dirs)
print('包含的文件:', files)
print()
批量读取文件名称
file_list = []
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(file_path)
遍历文件名,批量导入数据
all_data = pd.DataFrame()
for fp in sorted(file_list)[:300]:
print(fp)
df = pd.read_csv(fp, skiprows=1, encoding='gbk')
all_data = all_data.append(df, ignore_index=True)
对数据进行排序
all_data.sort_values(by=['交易日期', '股票代码'], inplace=True)
print(all_data)
将数据存入hdf文件中
all_data.to_hdf(
r'C:\Users\Simons\Desktop\xbx_stock_2019\data\a_stock.h5',
key='all_data',
mode='w'
)
从hdf中读取文件
all_data = pd.read_hdf(
r'C:\Users\Simons\Desktop\xbx_stock_2019\data\a_stock.h5',
key='all_data')
print(all_data)
=====将数据存入hdf文件
批量读取文件名称
file_list = []
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])
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=['交易日期'])
h5_store[stock_code] = df.iloc[:100]
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()
=== 第一种方法:将日线数据转为周线数据
将交易日期设定为index
df.set_index('交易日期', inplace=True)
周期转换方法:resample
rule_type = '1W'
period_df = df[['收盘价']].resample(rule=rule_type).last()
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()
period_df = period_df[['开盘价', '最高价', '最低价', '收盘价', '成交量']]
print(period_df)
exit()
=== 第二种方法:将日线数据转为一周数据
rule_type = '1W'
period_df = df.resample(rule=rule_type, on='交易日期', base=0, label='left', closed='left').agg(
{
'开盘价': 'first',
'最高价': 'max',
'最低价': 'min',
'收盘价': 'last',
'成交量': 'sum',
}
)
period_df = period_df[['开盘价', '最高价', '最低价', '收盘价', '成交量']]
print(period_df)
exit()
base参数:帮助确定转换周期开始的时间
label='left', closed='left',建议统一设置成'left'
=== 去除不必要的数据
去除一天都没有交易的周
print(period_df)
print(df[df['交易日期'] > pd.to_datetime('2000-01-23')])
exit()
period_df.dropna(subset=['开盘价'], inplace=True)
去除成交量为0的交易周期
period_df = period_df[period_df['成交量'] > 0]
print(period_df)
===rule的取值
print(df)
===== groupby常用操作汇总
根据'交易日期'进行group,将相同'交易日期'的行放入一个group,
print(df.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())
print(df.groupby('股票代码').head(3))
print(df.groupby('股票代码').tail(3))
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