pandas基础

本文详细介绍了Pandas库在股票数据分析中的基本使用,包括读取CSV数据、数据处理、统计分析、时间序列操作、数据筛选、排序、合并、去重、字符串处理、滚动窗口计算等。通过实例展示了如何利用Pandas进行数据清洗、计算平均值、最大值、最小值、标准差,以及如何进行数据排序、合并和去重,为后续的金融数据分析打下基础。
摘要由CSDN通过智能技术生成

pandas

以股票数据为例分析

一、基本使用
import pandas as pd  # 将pandas作为第三方库导入,我们一般为pandas取一个别名叫做pd

# =====导入csv数据
df = pd.read_csv(				#read_table、read_excel、read_json
    # 该参数为数据在电脑中的路径,
    # 要注意字符串转义符号 \ ,可以使用加r变为raw string或者每一个进行\\转义
    filepath_or_buffer=r'文件路径',
    # 编码格式,不同的文件有不同的编码方式,一般文件中有中文的,编码是gbk,默认是utf8
    encoding='gbk',
    # 该参数代表数据的分隔符,csv文件默认是逗号。其他常见的是'\t'
    sep=',',
    # 该参数代表跳过数据文件的的第1行不读入
    skiprows=1,
    # nrows,只读取前n行数据,若不指定,读入全部的数据
    # nrows=15,
    # 将指定列的数据识别为日期格式。若不指定,时间数据将会以字符串形式读入。一开始先不用。
    parse_dates=['交易日期'],
    # 将指定列设置为index。若不指定,index默认为0, 1, 2, 3, 4...
    index_col=['交易日期'],
    # 读取指定的这几列数据,其他数据不读取。若不指定,读入全部列
    # usecols=['交易日期', '收盘价'],
    # 当某行数据有问题时,报错。设定为False时即不报错,直接跳过该行。当数据比较脏乱的时候用这个。
    # error_bad_lines=False,
    # 将数据中的null识别为空值
    # na_values='NULL',
)
print(df)

print(df.shape)  # 输出dataframe有多少行、多少列。
print(df.shape[0])  # 取行数量,相应的列数量就是df.shape[1]
print(df.columns)  # 顺序输出每一列的名字,演示如何for语句遍历。
print(df.index)  # 顺序输出每一行的名字,可以for语句遍历。
print(df.dtypes)  # 数据每一列的类型不一样,比如数字、字符串、日期等。该方法输出每一列变量类型
print(df.head(3))  # 看前3行的数据,默认是5。与自然语言很接近
print(df.tail(3))  # 看最后3行的数据,默认是5。
print(df.sample(n=3))  # 随机抽取3行,想要去固定比例的话,可以用frac参数
print(df.describe())  # 非常方便的函数,对每一列数据有直观感受;只会对数字类型的列有效
# 对print出的数据格式进行修正
pd.set_option('expand_frame_repr', False)  # 当列太多时显示不清楚
pd.set_option("display.max_rows", 1000)  # 设定显示最大的行数
pd.set_option('precision', 1)  # 浮点数的精度
print(df.head())
# =====如何选取指定的行、列
print(df['开盘价'])  # 根据列名称来选取,读取的数据是Series类型
print(df[['交易日期', '收盘价']])  # 同时选取多列,需要两个括号,读取的数据是DataFrame类型
print(df[['开盘价']])
print(df.loc[['1999-11-11', '1999-11-25']])
#loc操作:通过label(columns和index的名字)来读取数据
print(df.loc['1999-11-11'])  # 选取指定的某一行,读取的数据是Series类型
print(df.loc[['2000-03-30', '2000-07-31']])  # 选取指定的两行
print(df.loc['2000-03-30': '2000-04-30'])  # 选取在此范围内的多行,和在list中slice操作类似,读取的数据是DataFrame类型
print(df.loc[:, '开盘价':'最低价'])  # 选取在此范围内的多列,读取的数据是DataFrame类型
print(df.loc['2000-03-30': '2000-07-31', '开盘价':'收盘价'])  # 读取指定的多行、多列。逗号之前是行的范围,逗号之后是列的范围。读取的数据是DataFrame类型
print(df.loc[:, :])  # 读取所有行、所有列,读取的数据是DataFrame类型
print(df.at['2000-03-30', '开盘价'])  # 使用at读取指定的某个元素。loc也行,但是at更高效。
print(df.loc['2000-03-30', '开盘价'])
# iloc操作:通过position来读取数据
print(df.iloc[0])  # 以index选取某一行,读取的数据是Series类型
print(df.iloc[1:3])  # 选取在此范围内的多行,读取的数据是DataFrame类型
print(df.iloc[:, 1:3])  # 选取在此范围内的多列,读取的数据是DataFrame类型
print(df.iloc[1:3, 1:3])  # 读取指定的多行、多列,读取的数据是DataFrame类型
print(df.iloc[:, :])  # 读取所有行、所有列,读取的数据是DataFrame类型
print(df.iat[1, 3])  # 使用iat读取指定的某个元素。使用iloc也行,但是iat更高效。
# 行列加减乘除
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())  # 求两列的均值,返回两个数,Series
print(df[['收盘价', '成交量']])
print(df[['收盘价', '成交量']].mean(axis=1))  # 求两列的均值,返回DataFrame。axis=0或者1要搞清楚。
axis = 1#代表对整几列进行操作。axis = 0(默认)代表对几行进行操作。实际中弄混很正常,到时候试一下就知道了。

print(df['最高价'].max())  # 最大值
print(df['最低价'].min())  # 最小值
print(df['收盘价'].std())  # 标准差
print(df['收盘价'].count())  # 非空的数据的数量
print(df['收盘价'].median())  # 中位数
print(df['收盘价'].quantile(0.25))  # 25%分位数

# =====shift类函数、删除列的方式
df['下周期收盘价'] = df['收盘价'].shift(-1)  # 读取上一行的数据,若参数设定为3,就是读取上三行的数据;若参数设定为-1,就是读取下一行的数据;
del df['下周期收盘价']  # 删除某一列的方法

df['涨跌'] = df['收盘价'].diff(1)  # 求本行数据和上一行数据相减得到的值
df.drop(['涨跌'], axis=1, inplace=True)  # 删除某一列的另外一种方式,inplace参数指是否替代原来的df
df['涨跌幅'] = df['收盘价'].pct_change(1)  # 类似于diff,但是求的是两个数直接的比例,相当于求涨跌幅

# =====cum(cumulative)类函数
df['累计成交量'] = df['成交量'].cumsum()  # 该列的累加值
print(df[['交易日期', '成交量', '累计成交量','涨跌幅']])
print((df['涨跌幅'] + 1.0).cumprod())  # 该列的累乘值,此处计算的就是资金曲线,假设初始1元钱。
# =====其他列函数
df['收盘价_排名'] = df['收盘价'].rank(ascending=True, pct=False)  # 输出排名。ascending参数代表是顺序还是逆序。pct参数代表输出的是排名还是排名比例
print(df[['收盘价', '收盘价_排名']])
del df['收盘价_排名']
print(df['收盘价'].value_counts())  # 计数。统计该列中每个元素出现的次数。返回的数据是Series
# =====数据筛选,根据指定的条件,筛选出相关的数据。
print(df['股票代码'] == 'sh600000')  # 判断交易股票代码是否等于sh600000
print(df[df['股票代码'] == 'sh600000'])  # 将判断为True的输出:选取股票代码等于sh600000的行
print(df[df['股票代码'] == 'sh600000'].index)  # 输出判断为True的行的index
print(df[df['股票代码'].isin(['sh600000', 'sh600004', 'sz000001'])])  # 选取股票代码等于'sh600000'或'sh600004'或'sz000001'的都行
print(df[df['收盘价'] < 10.0])  # 选取收盘价小于10的行
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'))  # 将带有空值的行删除。how='any'意味着,该行中只要有一个空值,就会删除,可以改成all。
print(df.dropna(subset=['月头', '收盘价'], how='all'))  # subset参数指定在特定的列中判断空值。
all代表全部为空,才会删除该行;any只要一个为空,就删除该行。

2.补全缺失值
print(df.fillna(value='N'))  # 直接将缺失值赋值为固定的值
df['月头'].fillna(value=df['收盘价'], inplace=True)  # 直接将缺失值赋值其他列的数据
print(df.fillna(method='ffill'))  # 向上寻找最近的一个非空值,以该值来填充缺失的位置,全称forward fill,非常有用
print(df.fillna(method='bfill'))  # 向下寻找最近的一个非空值,以该值来填充确实的位置,全称backward fill

3.找出缺失值
print(df.notnull())  # 判断是否为空值,反向函数为isnull()
print(df[df['月头'].notnull()])  # 将'月头'列为空的行输出

=====排序函数
print(df.sort_values(by=['交易日期'], ascending=1))  # by参数指定按照什么进行排序,acsending参数指定是顺序还是逆序,1顺序,0逆序
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))  # append操作,将df1和df2上下拼接起来。注意观察拼接之后的index。index可以重复
df3 = df1.append(df2, ignore_index=True)  # ignore_index参数,用户重新确定index
print(df3)


=====对数据进行去重
df3中有重复的行数,我们如何将重复的行数去除?
print(df3)
df3.drop_duplicates(
    subset=['交易日期', '股票代码'],  # subset参数用来指定根据哪类类数据来判断是否重复。若不指定,则用全部列的数据来判断是否重复
    keep='first',  # 在去除重复值的时候,我们是保留上面一行还是下面一行?first保留上面一行,last保留下面一行,False就是一行都不保留
    inplace=True
)
print(df3)


=====其他常用重要函数
df.reset_index(inplace=True, drop=True)  # 重置index
df.rename(columns={
    '收盘价': 'close',
    '开盘价': 'open',
    '股票代码': 'code',
    '股票名称': 'name',
    '交易日期': 'date',
    '最高价': 'high',
    '最低价': 'low',
    '前收盘价': 'prev_close',
    '成交量': 'volume',
    '成交额': 'money'}, inplace=True)  # rename函数给变量修改名字。使用dict将要修改的名字传给columns参数
print(df.empty)  # 判断一个df是不是为空,此处输出不为空
print(pd.DataFrame().empty)  # pd.DataFrame()创建一个空的DataFrame,此处输出为空
print(df.T)  # 将数据转置,行变成列,很有用

=====字符串处理
print(df['股票代码'])
print('sh600000'[:2])
print(df['股票代码'].str[:2])
print(df['股票代码'].str.upper())  # 加上str之后可以使用常见的字符串函数对整列进行操作
print(df['股票代码'].str.lower())
print(df['股票代码'].str.len())  # 计算字符串的长度,length
df['股票代码'].str.strip()  # strip操作,把字符串两边的空格去掉
print(df['股票代码'])
print(df['股票代码'].str.contains('767'))  # 判断字符串中是否包含某些特定字符
print(df['股票代码'].str.replace('sz', 'sh'))  # 进行替换,将sz替换成sh

=====rolling、expanding操作
计算'收盘价'这一列的均值
print(df['收盘价'])
如何得到每一天的最近3天close的均值呢?即如何计算常用的移动平均线?
使用rolling函数
df['收盘价_3天均值'] = df['收盘价'].rolling(3).mean()
print(df[['收盘价', '收盘价_3天均值']])
rolling(n)即为取最近n行数据的意思,只计算这n行数据。后面可以接各类计算函数,例如maxmin、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)  # 当列太多时显示完整

# =====导入sh600004的历史日线数据
df = pd.read_csv(
    r'...\sh600004.csv',
    encoding='gbk',
    skiprows=1, parse_dates=['交易日期']
)

# =====批量导入A股所有股票的历史日线数据
# 系统自带函数os.walk,用于遍历文件夹中的所有文件,os是python自带的系统库
# 演示os.walk

# file location存储我们要读取的数据的文件夹绝对路径
file_location = r'目标文件夹路径'

for root, dirs, files in os.walk(file_location):
    # root输出文件夹,dirs输出root下所有的文件夹,files输出root下的所有的文件
    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 = []
# 存储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()

=== 第一种方法:将日线数据转为周线数据
将交易日期设定为index
df.set_index('交易日期', inplace=True)

周期转换方法:resample
rule_type = '1W'  # rule='1W':意思是一周,意味着转变为周线数据
period_df = df[['收盘价']].resample(rule=rule_type).last()  # 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对象。不会做实质性操作,只是会判断是否可以根据该变量进行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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值