由于在很多股票分析中,需要用到从指定数据集中取的所需的数据,如指定的行、列或者序号位置,这就需要对数据集进行操作。Pandas的DataFrame为我们提供了很多方便的操作方式。下面介绍一下常用的方式。
一、获取原始数据
下面先用AKShare接口获取股票盈利预测数据并保存到example.xlsx文件,方便后面的各种操作。
代码如下:
import akshare as ak
import pandas as pd
df = ak.stock_profit_forecast() #获取盈利预测数据
df.to_excel('example.xlsx', sheet_name='盈利预测', index=False) #保存为*.xlsx文件
简单解释一下DataFram的基本结构:
1.行和列的序号都是从0开始;
2.行名和列名可作为标签使用来取行或者列数据。
3.索引值可以作为行名来使用。
3.iloc[]和loc[]的用途有部分重合,但不是一样,后面会详细说明。
二、DataFrame数据操作演示
1.读取和保存数据
(1)从Excel读取文件
从example.xlsx文件读取数据:
df = pd.read_excel('example.xlsx')
从example.xlsx文件读取表“盈利预测”:
df = pd.read_excel('example.xlsx', sheet_name='“盈利预测”')
(2)保存数据到Excel文件
保存数据到example.xlsx文件:
df.to_excel('example.xlsx')
保存数据到example.xlsx文件,表名为“盈利预测”:
df.to_excel('example.xlsx', sheet_name='盈利预测', index=False)
DataFrame还有将数据保存到CSV文件的to_csv(),将数据保存到sql数据库的to_sql(),将数据保存为html的to_html,以及将数据保存为jason的to_jason(),因为我这里没有用到,就不一一介绍了,大家可以自行查找相关资料。
2.数据处理和提取
(1)修改列名
由于上表中的中文名称不方便操作,下面把它全部改成英文:
data.columns='No','Code','Name','Num','Buy','Inc','Neu','Redu','Sell','EPS21','EPS22','EPS23','EPS24'] #重命名列名
更改指定列的列名:
df.rename(columns={'Num': 'RateNum'})
显示列名称:
df.columns
(2)数据显示设置
由于Python的显示宽度默认较小,因此中间的数据显示为…。为了方便观察,这把它设置为显示全部列,这样就可以看到所有数据了。
pd.set_option('display.width', 1000) # 设置字符显示宽度
pd.set_option('display.max_columns', None) # 设置显示最大列,None为显示所有列
看了上面这个盈利数据,你会发现几乎所有股票的评级都是买入和增持,连中性的都极少,这种评级完全没有意义,下面我们把它去掉,减少垃圾数据~~
(3)删除列
data1=data.drop(['Buy','Inc','Neu','Redu','Sell'], axis=1)
注意:axis=0表示按行删除,axis=1表示按列删除。
好了,这下没有不用数据干扰,我们继续演示。
删除指定标签的行:
data2=data.drop([0,1])
删除index指定是行:
data2=data.drop(index=[0,1])
注意:drop中的axis默认为0,即默认删除行,可以不指定。
(4)通过行列序号提取行列数据
提取表中的代码和名称(为了方便显示,这里只取前5行):
data.iloc[:5,1:3] #取表的第2列和第3列
结果如下:
注意:如果红框处参数写2,就只能取到第2列数据。
取第1行数据:data.iloc[0] 或 data.iloc[0,:]
取第1列数据:data.iloc[:,0]
取第2、3、4行的数据:data.iloc[1:4]
取第2行以后的数据:data.iloc[1:]
注意:iloc[]只能通过行列序号来获取数据。
获取第一行数据:data.loc[0]
获取第一至第五行数据:data.loc[0:5]
获取第一至第五行指定列的数据:data.loc[1:5,['Code','Name']]
获取第一至第五行从指定列开始的数据:data.loc[1:5,'Code':]
注意:loc[]的行参数为行序号时从0开始,也可以为行标签;列参数为列标签。
获取指定列中值为指定值的行:data1[data1['Code']==’600887’]
获取指定列中值大于指定值的行:
data1[data1['EPS21']>6]
获取行标签从’6’开始的行:
data1.loc['6':]
获取从开始到行标签为’8’的行:data1.loc[:'8']
注意,loc[]取单行数据只能用序号,不能用标签。比如以下情况会报错:
data1.loc['6']
data1[‘6’,’Code’]
data1.loc[['6','8']]
因此loc[]直接用行列标签取某个数据是行不通的,网上有些文章显示上面最后一个操作能用,如下图所示:
实测发现会报KeyError错误,下面会解释为什么我们这里会报错。另外,loc[]采用行号+列标签形式又可以,例如:
data1.loc[0,'Code']
大家猜猜下面这个操作会不会报错?
data1.loc[:'0','Code']
对于loc[]的操作总结一下:
a.行参数可以用序号和标签,但是单独操作某行时只能用序号,使用行标签只能操作多行数据。
这里要注意,使用序号操作的前提是表的index使用的为默认的数字序号,一旦你更改了index以后,序号操作可能失效,只能通过作为index的行标签操作。比如将data2的index改为列’Code’,你就会发现很多上面正常的操作都报错了。代码如下:
data1.index=data1.Code
data1.loc[0] #错误!!因为没有index为数字0的索引
data1.loc[0,'Code'] #错误!!因为没有index为数字0的索引
data1.loc['300957','Code'] #正确,因为当前index为Code列,其内容为str类型
data1.loc['300957'] #正确
b.列参数只能用标签,不能用序号。用的时候注意不要弄混了!
(5)获取单个数据
取列名为“Code”的列:data1['Code']
取第一行第二列元素:data1.iloc[0,1]
(6)索引设置
设置列“Code”为索引:data2.set_index('Code')
设置列“Name”为索引:data2.index = data2.Name
设置索引从0开始:
data2.index=range(len(data2))
(7)数据排序
按照指定列降序排列数据:
data1.sort_values('Code', ascending=False)
(8)修改指定列数据格式
将第一行的列“EPS21”到列“EPS24”的数据改为保留2为小数点:
line=data1.iloc[0,4:8].apply(lambda x:"%.2f" % x)
line=data1.loc[0,'EPS21':'EPS24'].apply(lambda x:"%.2f" % x)
将列“EPS21”的数据改为保留2为小数点:
data1['EPS21'].apply(lambda x:"%.2f" % x)
或者
data1['EPS21'].apply(lambda x:round(x,2))
(9)列数据转为list
data1['EPS21'].apply(lambda x:"%.2f" % x).tolist()
3.数据统计
获得列“EPS21”的最大值:data1['EPS21'].max()
获得列“EPS21”的最小值:data1['EPS21'].min()
获得列“EPS21”的均值:data1['EPS21'].mean()
获得列“EPS21”的中位数:data1['EPS21'].median()
获得列“EPS21”的标准差:data1['EPS21'].std()
获得列“EPS21”最大值的序号:data1['EPS21'].idxmax()
获得列“EPS21”最小值的序号:data1['EPS21'].idxmin()
在DataFrame数据处理的操作中有相当多的坑,需要去多实践和总结。本文仅介绍了DataFrame最常用到的一些数据操作,详细内容请参考官方文档:
https://www.pypandas.cn/docs/
-----------------------------------
原创不易,请多支持!对Python、量化和投资感兴趣请关注公众号:IntInvestor