pandas 是基于 Numpy 构建的,让以 Numpy 为中心的应用变得更加简单。
平台获取的数据主要是 DataFrame 的形式,它便是 pandas 中的。
除此之外,pandas 还包括 一位数组series 以及三维的Panel。
下面将进行详细介绍:
-
Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
-
DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。
-
Panel :三维的数组,可以理解为DataFrame的容器。
Pandas官网,更多功能请参考http://pandas-docs.github.io/pandas-docs-travis/index.html
# 首先导入库 import pandas as pd
1. Series
由一组数据(各种Numpy数据类型),以及一组与之相关的标签数据(即索引)组成。仅由一组数据即可产生最简单的Series,可以通过传递一个list对象来创建一个Series,pandas会默认创建整型索引,更多series内容请参考官网 http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html
创建一个Series:
s = pd.Series([1,3,5,np.nan,6,8])
s
获取 Series 的索引:
s.index
由于 Series 的用法在后续的 DataFrame 讲解及涉及,所以这了不做过多介绍,精彩内容请往下看。
2. DataFrame
DataFrame是一个表格型的数据结构,它含有一组有序的列,每一列的数据结构都是相同的,而不同的列之间则可以是不同的数据结构(数值、字符、布尔值等)。或者以数据库进行类比,DataFrame中的每一行是一个记录,名称为Index的一个元素,而每一列则为一个字段,是这个记录的一个属性。DataFrame既有行索引也有列索引,可以被看做由Series组成的字典(共用同一个索引)。
更多内容请参考:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html
2.1 创建一个DataFrame,包括一个numpy array, 时间索引和列名字:
dates = pd.date_range('20130101',periods=6) df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
2.2 查看数据
我们以聚宽平台获取的数据为例:
from jqdatasdk import * auth("username", "password") # print(is_auth()) zgpa = get_price("603138.XSHG", start_date="2020-05-01", end_date="2020-5-14", frequency="daily", fields=["open", "high", "low", "close"]) # print(zgpa) # 一个DateFrame对象 # print(zgpa.head()) # 获取前几行数据 # print(zgpa.tail()) # 获取最后几行数据 # print(zgpa.index) # 获取索引 # print(zgpa.columns) # 获列 # print(zgpa.values) # 获取值 # print(zgpa.describe()) # 获取汇总数据 # print(zgpa.T) # 转置 # print(zgpa.sort_values(by="close")) # 对某一列排序,不改变原DateFrame对象
2.3 选择数据
2.3.1 通过下标选取数据:
df['open'],df.open 以上两个语句是等效的,都是返回 df 名称为 open 列的数据,返回的为一个 Series。 df[0:3], df['2016-07-05':'2016-07-08'] 下标索引选取的是 DataFrame 的记录,与 List 相同 DataFrame 的下标也是从0开始,区间索引的话,为一个左闭右开的区间,即[0:3]选取的为0-2三条记录。 与此等价,还可以用起始的索引名称和结束索引名称选取数据,如:df['a':'b']。有一点需要注意的是使用起始索引名称和结束索引名称时,也会包含结束索引的数据。具体看下方示例: 以上两种方式返回的都是DataFrame。
# print(zgpa["open"]) # 选择open列的数据 # print(zgpa.low) # 选择low列的数据 # print(zgpa[["open", "close"]]) # 选择多列数据 # print(zgpa[1:3]) # 选择多行数据 # print(zgpa[0:3]) # 选择多行数据 # print(zgpa["2020-05-08": "2020-05-13"]) # 按照index选取区间数据
2.3.2 使用标签选取数据:
df.loc[行标签,列标签] df.loc['a':'b'] #选取 a到b 行数据 df.loc[:,'open'] #选取 open 列的数据 df.loc 的第一个参数是行标签,第二个参数为列标签(可选参数,默认为所有列标签),两个参数既可以是列表也可以是单个字符,如果两个参数都为列表则返回的是 DataFrame,否则,则为 Series。 PS:loc为location的缩写。
# 使用标签选取数据 # print(zgpa.loc["2020-05-08", "open"]) # 2020-05-08 行中的open列数据,返回series对象 # print(zgpa.loc["2020-05-08", ]) # 2020-05-08 行中的所有列的数据 # print(type(zgpa.loc["2020-05-08", ["close", "open"]])) # 2020-05-08 行中的所有列的数据 # print(zgpa.loc["2020-05-08": "2020-05-13"]) # 2020-05-08 至 2020-05-13 行中的所有列的数据, 返回一个DateFrame对象
2.3.3. 使用位置选取数据:
df.iloc[行位置,列位置] df.iloc[1,1] #选取第二行,第二列的值,返回的为单个值 df.iloc[[0,2],:] #选取第一行及第三行的数据 df.iloc[0:2,:] #选取第一行到第三行(不包含)的数据 df.iloc[:,1] #选取所有记录的第二列的值,返回的为一个Series df.iloc[1,:] #选取第一行数据,返回的为一个Series PS:iloc 则为 integer & location 的缩写
# 使用位置选取数据 # print(zgpa.iloc[1, 2]) # 获取第二行,第三列的数据 # print(zgpa.iloc[1:5, ]) # 获取第2行至第5行的所有列数据 # print(zgpa.iloc[1:5, :]) # 获取第2行至第5行的所有列数据 # print(zgpa.iloc[:, 2]) # 获取所有行的第三列数据, 返回的为一个Series # print(zgpa.iloc[1, :]) # 获取第一行的所有数据, 返回的为一个Series
2.3.4 通过逻辑指针进行数据切片:
df[逻辑条件] df[df.one >= 2] #单个逻辑条件 df[(df.one >=1 ) & (df.one < 3) ] #多个逻辑条件组合
# 通过逻辑进行数据切片 # print(zgpa[zgpa.close < 21]) # 获取收盘价大于21的天数 数据 # print(zgpa[(zgpa.open > 20) & (zgpa.close < 21)]) # 获取开盘价大于20,并且收盘价小于21的天数数据 # print(zgpa[(zgpa.open > 20) | (zgpa.close < 21)]) # 获取开盘价大于20,或者收盘价小于21的天数数据
使用isin方法过滤数据
# print(zgpa["close"].isin([20.80, ])) # 获取close列中,值是否有符合20.80的数,不符合返回false # print(zgpa[zgpa["close"].isin([20.80, ])]) # 获取close列中,值为20.80的数
上一节我们介绍了 DataFrame 的数据查看与选择
本节主要讲解 DataFrame 的数据处理,包括缺失数据处理、函数的应用和映射、数据规整、分组等。
# 首先导入库 import pandas as pd # 获取平安银行近几个工作日的开盘价、最高价、最低价、收盘价。 df = get_price('000001.XSHE',start_date='2016-07-01', end_date='2016-07-20', frequency='daily', fields=['open','high','low','close']) df[df > 9.0] = NaN df
df.fillna(value=0)
pd.isnull(df)
df.mean()#列计算平均值 open 8.831538 high 8.863636 low 8.812857 close 8.855385 dtype: float64 df.mean(1)#行计算平均值 2016-07-01 8.7025 2016-07-04 8.7575 2016-07-05 8.8025 2016-07-06 8.7925 2016-07-07 8.7775展开输出 ↓ 2016-07-08 8.7625 2016-07-11 8.7575 2016-07-12 8.8150 2016-07-13 8.9100 2016-07-14 8.9550 2016-07-15 8.9625 2016-07-18 8.9800 2016-07-19 8.9600 2016-07-20 8.9650 dtype: float64 df.mean(axis = 1,skipna = False) # skipna参数默认是 True 表示排除缺失值 2016-07-01 8.7025 2016-07-04 8.7575 2016-07-05 8.8025 2016-07-06 8.7925 2016-07-07 8.7775展开输出 ↓ 2016-07-08 8.7625 2016-07-11 8.7575 2016-07-12 8.8150 2016-07-13 NaN 2016-07-14 8.9550 2016-07-15 8.9625 2016-07-18 NaN 2016-07-19 NaN 2016-07-20 8.9650 dtype: float64 df.sort_index()#行名字排序
df.sort_index(axis=1)#列名字排序
# 数据默认是按升序排序的,也可以降序排序 df.sort_index(axis=1,ascending = False)
常用的方法如上所介绍们,还要其他许多,可自行学习,下面罗列了一些,可供参考:
count 非na值的数量 describe 针对Series或个DataFrame列计算汇总统计 min、max 计算最小值和最大值 argmin、argmax 计算能够获取到最大值和最小值得索引位置(整数) idxmin、idxmax 计算能够获取到最大值和最小值得索引值 quantile 计算样本的分位数(0到1) sum 值的总和 mean 值得平均数 median 值得算术中位数(50%分位数) mad 根据平均值计算平均绝对离差 var 样本值的方差 std 样本值的标准差 skew 样本值得偏度(三阶矩) kurt 样本值得峰度(四阶矩) cumsum 样本值得累计和 cummin,cummax 样本值得累计最大值和累计最小值 cumprod 样本值得累计积 diff 计算一阶差分(对时间序列很有用) pct_change 计算百分数变化
df1 = get_price('000001.XSHE',start_date='2016-07-05', end_date='2016-07-08', frequency='daily', fields=['open','high','low','close']) df1
df2 = get_price('000001.XSHE',start_date='2016-07-12', end_date='2016-07-15', frequency='daily', fields=['open','high','low','close']) df2
纵向拼接(默认):
pd.concat([df1,df2],axis=0)
横向拼接,index对不上的会用 NaN 填充:
pd.concat([df1,df2],axis=1)
下面演示一下index 可以对上情况的横向拼接结果:
df3 = get_price('000001.XSHE',start_date='2016-07-12', end_date='2016-07-15', frequency='daily', fields=['low','close']) df4 = get_price('000001.XSHE',start_date='2016-07-12', end_date='2016-07-15', frequency='daily', fields=['open','high']) pd.concat([df3,df4],axis=1)
df1
s = df1.iloc[0] s open 8.80 high 8.83 low 8.77 close 8.81 Name: 2016-07-05 00:00:00, dtype: float64 df1.append(s, ignore_index=False) # ignore_index=False 表示索引不变
df1.append(s, ignore_index=True) # ignore_index=True 表示索引重置
z = df1.append(s, ignore_index=False)
z
查看重复数据:
z.duplicated() 2016-07-05 False 2016-07-06 False 2016-07-07 False 2016-07-08 False 2016-07-05 True展开输出 ↓ dtype: bool 移除重复数据: z.drop_duplicates()
4 分组
z.groupby('open').sum()
z.groupby(['open','close']).sum()
df9 = get_price(['000001.XSHE','000002.XSHE'],start_date='2016-07-12', end_date='2016-07-15', frequency='daily', fields=['open','high','low','close']) df9 <class 'pandas.core.panel.Panel'> Dimensions: 4 (items) x 4 (major_axis) x 2 (minor_axis) Items axis: close to open Major_axis axis: 2016-07-12 00:00:00 to 2016-07-15 00:00:00 Minor_axis axis: 000001.XSHE to 000002.XSHE df9[:,0,:]
df9[:,:,0]
df9[:,:,1]
df9[0,:,:]
df9.ix[:,0]