一、导入csv文件时,使用pd.read_csv()函数。使用时注意事项如下:
1.文件路径的选择-filepath_or_buffer
2.编码设置- encoding='gbk'
3.表头内容是否跳过不读- skiprows=1
4.只读取多少行的内容-# nrows=15
5.指定某列作为日期格式,否则以字符串类似数据读入-parse_dates=['交易日期']
6.指定某列作为index,否则默认01234等- index_col=['交易日期']
7.读取指定的这几列日期,其他数据不读取。若不指定, 读取全部列-usecols=['交易日期', '收盘价']
8.使用read_csv导入数据非常方便, 导入的数据的数据类型是DataFrame。
二、查看选取数据
===看数据===
# print(df.shape) # 输出dataframe一共有多少行和多少列
# print(df.shape[0]) # 取行数量,相应的列数量就是df.shape[1]
# print(df.columns) # 顺序输出每一列的名字,演示如何for语句遍历。
# for col in df.columns:
# print(col)
# print(df.index) # 顺序输出每一行的名字,可以for语句遍历。
# for idx in df.index:
# print(idx)
# print(df.dtypes) # 数据每一列的类型不一样,比如数字、字符串、日期等。该方法输出每一列变量类型
# print(df.head(3)) # 看前3行的数据,默认是5。与自然语言很接近
# print(df.tail(3)) # 看最后3行的数据,默认是5。
# print(df.sample(frac=0.5)) # 随机抽取3行, 或者用frac(百分之)
# print(df.describe()) # 非常方便的函数,对每一列数据有直观感受;只会对数字类型的列有效
===对print出的数据格式进行修正===
# pd.set_option('expand_frame_repr', False) # 当列太多时不换行 此代码的位置一般处于刚import结束时
# pd.set_option('max_colwidth', 1) # 设定每一列的最大宽度
# pd.set_option("display.max_rows", 1000) # 设定显示最大的行数 None 为显示所有行
# pd.set_option('precision', 1) # 浮点数的精度
# print(df)
更多设置请见https://pandas.pydata.org/pandas-docs/stable/options.html
===如何选取指定的行和列===
# print(df['开盘价']) # 根据列名称来选取, 读取的数据是Series类型
# print(df[['交易日期', '收盘价']]) # 同时选取多列, 注意需要两个括号,读取的数据是DataFrame类型
# loc(location)操作: 通过label(columns和index的名字)来读取数据
# 需要关闭parse_dates, 打开index_col
# print(df.loc['1999/11/11']) # 选取指定的某一行,读取的数据是Series类型
# print(df.loc[['1999/11/11', '1999/11/19']]) # 通过切片选取指定的两行
# print(df.loc['2000/3/30': '2000/4/28']) # 选取在此范围内的多行,和在list中slice操作类似,读取的数据是DataFrame类型
# print(df.loc[:, '开盘价':'收盘价']) # 选取在此范围内的多列,读取的数据是DataFrame类型
# print(df.loc['2000/3/30': '2000/7/31', '开盘价': '收盘价']) # 读取指定的多行、多列。逗号之前是行的范围,逗号之后是列的范围。读取的数据是DataFrame类型
# print(df.at['2000/3/30', '开盘价']) # # 使用at读取指定的某个元素。loc也行,但是at更高效。
# print(df.loc['2000/3/30', '开盘价'])
以上是我认为最常用的函数
哪里可以看到全部的函数?https://pandas.pydata.org/pandas-docs/stable/api.html
三、列操作
===行列加减乘除===
# print(df['交易日期'] + ' 15:00:00') # 字符串列可以直接加上字符串,对整列进行操作
# print(df['收盘价'] * 100) # 数字列直接加上或者乘以数字,对整列进行操作。
# print(df[['收盘价', '成交量']])
# print(df['收盘价'] * df['成交量']) # 两列之间可以直接操作。收盘价*成交量
===新增一列===
# df['交易日期2'] = df['交易日期'] + ' 00:00:00 '
# print(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,就是读取下一行的数据;
# print(df[['收盘价', '下周期收盘价']])
# del df['下周期收盘价'] # 删除某一列的方法
# df['涨跌'] = df['收盘价'].diff(1) # 求本行数据和上一行数据相减得到的值, 改为3的话,就是上3行数据相减得到的值, 改为-1的话就是下一行数据相减得到差值
# df.drop(['涨跌'], axis=1, inplace=True) # 删除某一行的另外一种方式, inplace参数指是否替代原来的df
# df.drop(['涨跌', '收盘价'], axis=1, inplace=True) # 删除多行数据
# df['涨跌幅'] = df['收盘价'].pct_change(1) # 类似于diff, 但是求的是两个数直接的比例,相当于求涨跌幅
===cum(cumulative)类函数===
# df['累计成交量'] = df['成交量'].cumsum() # 该列的累加值
# print(df[['交易日期', '成交量', '累计成交量']])
# df['涨跌幅'] = df['收盘价'].pct_change(1)
# print((df['涨跌幅']+1.0).cumprod()) # 该列的累乘值, 此处计算的就是资金曲线, 假设初始1元钱。
===其他列函数===
# df['收盘价_排名'] = df['收盘价'].rank(ascending=False, pct=False) # 输出排名。ascending参数代表是顺序还是逆序。pct参数代表输出的是排名还是排名比例
# print(df[['收盘价', '收盘价_排名']])
print(df['收盘价'].value_counts()) # 计数。统计该列中每个元素出现的次数,返回的数据是Series
以上是我认为最常用的函数
哪里可以看到全部的函数?https://pandas.pydata.org/pandas-docs/stable/api.html
四、数据筛选
===根据指定条件,筛选出相关的数据===
# print(df['股票代码'] == 'sh600000') # 逐行判断交易股票代码是否等于sh600000
# print(df[df['股票代码'] == 'sh600000']) # 将判断为True的输出:选取股票代码等于sh600000的行
# print(df[df['股票代码'] == 'sh600000'].index) # 输出判断为True的行的index
"""
df['股票代码'].isin(['sh600000', 'sh600004', 'sz000001']) 判定股票代码在不在我指定的这个list当中
白话说就是先判定股票代码是不是'sh600000', 'sh600004', 'sz000001'
然后把代码放进print(df[])
就成了
print(df[df['股票代码'].isin(['sh600000', 'sh600004', 'sz000001']) ])
"""
# print(df[df['股票代码'].isin(['sh600000', 'sh600004', 'sz000001'])]) # 选取股票代码等于'sh600000'或'sh600004'或'sz000001'的都行
# print(df[df['收盘价'] < 10.0]) # 选取收盘价小于10的行
"""
(df['收盘价'] < 10.0)
(df['股票代码'] == 'sz300641')
(df['收盘价'] < 10.0) & (df['股票代码'] == 'sz300641')
"""
print(df[(df['收盘价'] < 10.0) & (df['股票代码'] == 'sz300641')]) # 两个条件同时成立用&,或者的话就是| 注意此用法仅适用于pandas模块中
print(df[(df['收盘价'] < 10.0) | (df['股票代码'] == 'sz300641')])
注意项:and: 相当于& or: 相当于|
六、数据整理
===排序函数===
# print(df.sort_values(by=['交易日期'], ascending=0)) # by参数指定按照什么进行排序,acsending参数指定是顺序还是逆序,1顺序,0逆序
# print(df.sort_values(by=['股票代码', '交易日期'], ascending=[0, 0])) # 按照多列进行排序
两个df上下合并操作,append操作
df1 = df.iloc[0:10][['交易日期', '股票代码', '收盘价', '成交量']] # 先取0到9行,然后从这10行取出这四列
# print(df1)
df2 = df.iloc[5:15][['交易日期', '股票代码', '收盘价', '成交量']]
# print(df2)
print(df1.append(df2)) # append操作, 将df1和df2上下拼接起来。注意观察拼接之后的index。index可以重复。但是因为会有重复的index,所以需要重新设定index
df3 = df1.append(df2, ignore_index=True) # ignore_index参数, 用户重新确定index
# print(df3)
===两个df上下合并操作,append操作===
df1 = df.iloc[0:10][['交易日期', '股票代码', '收盘价', '成交量']] # 先取0到9行,然后从这10行取出这四列
# print(df1)
df2 = df.iloc[5:15][['交易日期', '股票代码', '收盘价', '成交量']]
# print(df2)
print(df1.append(df2)) # append操作, 将df1和df2上下拼接起来。注意观察拼接之后的index。index可以重复。但是因为会有重复的index,所以需要重新设定index
df3 = df1.append(df2, ignore_index=True) # ignore_index参数, 用户重新确定index
# print(df3)
===对数据去重===
# df3中有重复的行数,我们如何将重复的行数去除?
df3.drop_duplicates(
subset=['交易日期', '股票代码'], # subset参数用来指定根据哪类数据来判断是否重复。若不指定,则用全部列的数据来判断是否重复
keep='first', # 在去除重复值的时候,我们是保留上面一行还是下面一行?first保留上面一行;last保留下面一行;False就是一旦有两行都重复的话,这两行都不保留
inplace=True
)
# print(df3)
===其他常用重要函数===
# df.reset_index(inplace=True, drop=False) # 重置index, drop=False(系统默认为False)等于将原有的index保留并且会形成新的一列留在原始数据中,drop=True就等于将原来index直接去除
# print(df)
# df.rename(columns={'收盘价': 'close', # rename函数给变量修改名字。使用dict将要修改的名字传给columns参数
'开盘价': 'open',
'股票代码': 'code',
'股票名称': 'name',
'交易日期': 'date',
'最高价': 'high',
'最低价': 'low',
'前收盘价': 'prev_close',
'成交量': 'volume',
'成交额': 'money'
}, inplace=True)
print(df.empty) # 判断一个df是不是为空,此处输出不为空
print(pd.DataFrame().empty) # pd.DataFrame()创建一个空的DataFrame,此处输出为空
print(df.T) # 矩阵概念:将数据转置,行变成列,很有用
八、pandas中的时间处理
===时间处理===
print(df['交易日期']) # 严格意义上说它不是日期格式,而是一个字符串
print(df.at[0, '交易日期']) # 通过at拿到"交易日期"这一竖列中第一行的数据
print(type(df.at[0, '交易日期'])) # 通过type查看下数据类型 结果显示为类型为str
# pd.to_datetime() 该函数可以将str转化为时间格式的数据类型
# df['交易日期'] = pd.to_datetime(df['交易日期']) # 将交易日期由字符串改为时间变量
# print(df.at[0, '交易日期'])
# print(type(df.at[0, '交易日期'])) # 结果变成了<class pandas._libs.tslibs.timestamps.Timestamp>
# pd.to_datatime()的强大,看下面几个例子
# print(pd.to_datetime('1999-01-01'))
# print(pd.to_datetime('1999-1-1'))
# print(pd.to_datetime('1999/01/01'))
# print(pd.to_datetime('1999/1/1'))
# print(pd.to_datetime('19990101'))
# print(pd.to_datetime('199911')) # 唯一一个报错的代码
# print(pd.to_datetime('1999年1月11日')) # 报错:Unknown string format: 1999年1月11日
# df['交易日期'] = pd.to_datetime(df['交易日期'])
# print(df['交易日期'])
# print(df['交易日期'].dt.day) # # 输出这个日期的年份。相应的month是月份,day是天数,还有hour, minute, second
# print(df['交易日期'].dt.week) # dt.week已经提示future warning 要求更换成dt.isocalendar().week
# print(df['交易日期'].dt.isocalendar().week) # 一年中的第几周
# print(df['交易日期'].dt.dayofyear) # 这一天是一年当中的第几天
# print(df['交易日期'].dt.dayofweek) # 这一天是一周当中的第几天,0代表星期一
# print(df['交易日期'].dt.weekday) # 和上面函数相同,更加常用
# print(df['交易日期'].dt.day_name()) # 和上面函数相同,但返回的是星期几的英文: weekday_name已经弃用, 改为day_name()
# print(df['交易日期'].dt.days_in_month) # 这一天所在月份有多少天
# print(df['交易日期'].dt.is_month_start) # 这一天是否是该月的开头, 是否存在is_month_end?
# print(df['交易日期'].dt.is_month_end) # 这一天是否是该月的结尾
# print(df['交易日期'] + pd.Timedelta(days=1)) # 增加一天, Timedelta用于表示时间差数据, [weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds]
# print((df['交易日期'] + pd.Timedelta(days=1)) - df['交易日期']) # 增加一天然后再减去今天的日期
九、滚动操作
===rolling、expanding操作===
# 计算"收盘价"这一列的均值
# print(df['收盘价'].mean())
# 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天的均值,如果想计算每天的从1开始至今的均值, 应该如何计算?
===使用expanding操作===
# df['收盘价_至今均值'] = df['收盘价'].expanding().mean()
# print(df[['收盘价', '收盘价_至今均值']])
# expanding即为取从头至今的数据.后面可以接各类计算函数
print(df['收盘价'].expanding().max())
print(df['收盘价'].expanding().min())
print(df['收盘价'].expanding().std())
rolling和expanding简直是为量化领域量身定做的方法, 经常会用到。
===输出到本地文件===
df['收盘价_至今均值'] = df['收盘价'].expanding().mean()
print(df)
df.to_csv(r'E:\pycharm projects\new_stock_projects\data\output.csv', encoding='gbk', index=False) # 存储到csv文件的汉字发生乱码了