数据分析入门
第三天 参考视频
四、Pandas使用 - 基础篇
(一)概述
-
Pandas介绍 - 数值处理工具
pan - panel 面板数据
d- data
as - analysis 分析
-
Pandas优点
(1)便捷的数据处理
(2)读取文件方便
(3)封装了Matplotlib、Numpy的画图和计算
-
Pandas核心数据结构
(1)DataFrame
-
创建
# 结构:既有行索引(index),又有列索引(columns)的二维数组 stock_change = np.random.normal(0, 1, (10,5)) pd.DataFrame(stock_change) # 行索引 stock_code = ['股票{}'.format(i) for i in range(10)] # 列索引 date = pd.date_range(start='20190606', periods=5, freq='B') pd.DataFrame(stock_change, index=stock_code, columns=date)
-
属性
# 可用此方式创建,也可用字典方式创建 data = pd.DataFrame(stock_change, index=stock_code, columns=date) data.shape # shape=(10,5) data.index # index=stock_code data.columns # columns=date data.values # 除去index和columns的数据部分,即一个二维数组 data.T # 包含index和columns的行列转换
-
方法
data = pd.DataFrame(stock_change, index=stock_code, columns=date) data.head(n) # 返回前n行values(带有index和columns),不写默认返回前5行values data.tail() # 返回后n行values(带有index和columns),不写默认返回后5行values
-
DataFrame索引的设置
# 修改行列索引值 # data.index[3] = 'aaa' # 不能单独修改行列索引值,只能整体修改 stock_code = ['股票----{}'.format(i) for i in range(10)] data.index = stock_code # 重设索引 data.reset_index(drop=True) # 删除原索引,然后重设索引 data.reset_index() # 将原索引作为index列插入原数据,然后重设索引 # 设置新索引 df = pd.DataFrame({'month':[1, 4, 7, 10], 'year':[2012, 2014, 2013, 2014], 'sale':[55, 40, 84, 31]}) # 以月份设置新的索引 df.set_index('month', drop=True) # 默认drop=True删除values中month列,否则保留 # 设置多个索引 df_mul = df.set_index(['month', 'year'], drop=True) df_mul.index ''' Results: MultiIndex([( 1, 2012), ( 4, 2014), ( 7, 2013), (10, 2014)], names=['month', 'year']) 从Index变成了MultiIndex ''' df_mul.index.names # FrozenList(['month', 'year']) df_mul.index.levels # FrozenList([[1, 4, 7, 10], [2012, 2013, 2014]])
(2)Panel - DataFrame的容器,三维
np.panel()在最新版已被移除,使用MultiIndex代替
(3)Serise - 带索引(行索引)的一维数组,DataFrame是Serise的容器
-
初识Serise
data = pd.DataFrame(stock_change, index=stock_code, columns=date) data.iloc[1,:] # Serise带索引的一维数组 ''' Results: 2020-06-18 0.924080 2020-06-19 0.016468 2020-06-22 -1.266148 2020-06-23 1.523937 2020-06-24 -0.853731 Freq: B, Name: 股票_1, dtype: float64 '''
-
Serise 属性
# index data.iloc[1,:].index ''' Results: DatetimeIndex(['2020-06-18', '2020-06-19', '2020-06-22', '2020-06-23', '2020-06-24'], dtype='datetime64[ns]', freq='B') ''' # values 是一个一维ndarray数组 data.iloc[1,:].values ''' Results: array([ 0.92407994, 0.01646795, -1.26614793, 1.52393669, -0.85373051]) '''
-
Serise 创建/方法
# 1.指定索引 pd.Series([6.7,5.6,3,10,2],index=['a','b','c','d','e']) # 2.通过字典创建 键作为index,值作为values pd.Series({ 'red':100, 'blue':200, 'green':500, 'yellow':1000 })
-
(二)基本数据操作
-
读取数据
datas = pd.read_csv('C:/Users/ABC/Desktop/stock_day.csv') datas = datas.drop(['ma5', 'ma10', 'ma20', 'v_ma5', 'v_ma10', 'v_ma20'], axis=1) # 对列drop datas # datas值如下
open high close low volume 2018-02-27 23.53 25.88 24.16 23.53 95578.03 2018-02-26 22.80 23.78 23.53 22.80 60985.11 2018-02-23 22.88 23.37 22.82 22.71 52914.01 … … … … … … -
索引操作
# 直接使用行列索引(必须先列后行) datas['open']['2018-02-26'] # 22.80 # 按名字索引 loc datas.loc['2018-02-26']['open'] # 22.80 # datas.loc['2018-02-26','open'] # 这样也可以 # 按数字索引 iloc 不能直接进行数字索引 datas.iloc[1][0] # 22.80 #组合索引 数字、名字 # 获取前四行四列元素值 # datas.ix[0:4, ['open', 'close', 'high', 'low']] 此方法已废弃 # loc datas.loc[datas.index[:4], ['open', 'close', 'high', 'low']] #d atas.index[:4]获取行索引名字 # iloc # datas.columns.get_indexer(['open', 'close', 'high', 'low']) # array([0, 2, 1, 3], dtype=int64) datas.iloc[0:4, datas.columns.get_indexer(['open', 'close', 'high', 'low'])] #d atas.index[:4]获取行索引名字 # 一个低级语法错误 # 以下这句报语法错误 # datas.iloc[[0:4], datas.columns.get_indexer(['open', 'close', 'high', 'low'])] # 以下这句就不会 datas.iloc[[0,1,2,3], datas.columns.get_indexer(['open', 'close', 'high', 'low'])] # 以上两句主要原因是[0:4]本身是错的,切分是对某一个矩阵/列表等切分,自己不能切分,应该用range(4) datas.iloc[range(4), datas.columns.get_indexer(['open', 'close', 'high', 'low'])]
-
赋值操作
# 可以修改整列或整行 datas["open"] = 5 # 或者datas.open = 1 # 修改某一个元素值 四种索引索引到该元素再直接赋值即可 datas.iloc[0,0] = "hehehe"
-
排序
(1)对DataFrame内容排序
# 对内容进行排序, ascending=False降序排列 ,默认为True升序排列 datas.sort_values(by="high",ascending=False) # 按照多个字段进行排序 # 先按照“high”字段的内容进行排序,如果值相同,再按照“close”字段的内容进行排序 datas.sort_values(by=["high","close"]) # 实现先按照“high”字段的内容进行“升序”排序,如果值相同,再按照“close”字段的内容进行“降序”排序 datas.sort_values(by=["high","close"],ascending=[True, False])
(2)对DataFrame索引排序
# 按照行索引大小进行排序,默认从小到大排序 datas.sort_index()
(3)对serise排序
# 获取一个serise sr = datas["open"] # 对serise内容排序,ascending=False降序排列 ,默认为True升序排列 sr.sort_values(ascending=False) # 对serise索引排序,ascending=False降序排列 ,默认为True升序排列 sr.sort_index()
(三)DataFrame运算
-
算术运算
# 对Series类型进行操作 datas["high"] + 3 # add()能进行head()操作 datas["high"].add(3).head() # 对DataFrame类型进行操作 datas + 3 datas.sub(3) # 两列相减 datas["close"].sub(datas["open"])
-
逻辑运算
# 逻辑运算符 datas['high'] > 2 # 返回series,带索引的布尔值组 ''' Results: 2018-02-27 True 2018-02-26 True ... 2015-03-03 True 2015-03-02 False Name: high, Length: 643, dtype: bool ''' # 满足high>25的所有项(布尔索引) datas[datas['high'] > 25] # 多个逻辑判断 datas[(datas["high"]>25) & (datas["open"]< 24)]
# 逻辑运算函数 # query() 类似于数据库查询语句 datas.query("high>25 & open<24") # isin() datas['high'].isin([25,26]) # high值是否为25或26,而不是25到26之间(两者之间用query就好);返回series,带索引的布尔值组,可布尔索引 ''' 2018-02-22 False 2018-02-14 False ... 2015-03-03 False 2015-03-02 False Name: high, Length: 643, dtype: bool '''
-
统计运算
# 计算每一列的总数,均值,标准差,最小值,分位数,最大值等 datas.describe() datas[["open", "high"]].describe() ''' Results: open high count 643.000000 643.000000 mean 21.272706 21.900513 std 3.930973 4.077578 min 12.250000 12.670000 25% 19.000000 19.500000 50% 21.440000 21.970000 75% 23.400000 24.065000 max 34.990000 36.350000 ''' # min max mean median var std # axis=0 求每一列的最大值 axis=1求每一行的最大值 datas.max(axis=0) # 累计统计函数 计算前1/2/3.../n-1/n天累计(若是累加,可以看出变化趋势) # cumsum累加 cummax累计最大 cummin累计最小 cumprod累乘 datas["p_change"].cumsum() # 计算每天变化累计值,变化趋势 datas["p_change"].sort_index().cumsum().plot() # 先以时间排序,再画图
-
自定义运算
''' apply(func, axis=0) func:自定义函数 axis=0:默认是列,axis=1为行进行运算 ''' # 自定义一个计算最大值减去最小值的函数 datas.apply(lambda x : x.max()-x.min(),axis=0)
(四)Pandas画图
-
# 查看volume和turnover之间的关系 datas.plot(x="volume",y="turnover",kind="scatter")
(五)文件读取与存储
-
CSV
(1)读取CSV文件
# usecols:指定读取的列名,列表形式 datas = pd.read_csv('C:/Users/ABC/Desktop/stock_day.csv',usecols=['open', 'close', 'high', 'low']) # datas = datas.drop(['ma5', 'ma10', 'ma20', 'v_ma5', 'v_ma10', 'v_ma20'], axis=1) # 对列drop datas.head() # names:如果数据集本身没有列名,可以自己指定列名,不然会默认第行第一列作为字段名 datas = pd.read_csv('C:/Users/ABC/Desktop/stock_day2.csv',names=['open', 'close', 'high', 'low', 'ma5', 'ma10', 'ma20', 'v_ma5', 'v_ma10', 'v_ma20']) # 上面的列名数10<数据所有列数15,会将数据5列第一行作为字段名,后10列用所给字段名 datas.head()
(2)存储CSV文件
# 保存open列前10行数据 # 保存的时候index=False去掉行索引 # mode="a" 追加数据,mode="b" 重写数据 # header=False 不要重复追加列名 datas[:10].to_csv("C:/Users/ABC/Desktop/open.csv",columns=['open'],index=False,mode="a",header=False) # 保存open列前10行 datas[:10].to_csv("C:/Users/ABC/Desktop/open.csv",columns=['open']) # 读取刚才保存文件 datas = pd.read_csv('C:/Users/ABC/Desktop/open.csv') ''' Datas: Unnamed: 0 open 0 2018-02-27 23.53 1 2018-02-26 22.80 2 2018-02-23 22.88 ''' # 有一个unnamed列,应该将此列作为行索引的 datas = pd.read_csv('C:/Users/ABC/Desktop/open.csv',index_col=0) ''' Datas: open 2018-02-27 23.53 2018-02-26 22.80 2018-02-23 22.88 '''
-
HDF5
# hdf5 存储 3维数据的文件 # key1 dataframe1二维数据 # key2 dataframe2二维数据 path = 'C:/Users/ABC/Desktop/open.h5' pd.read_hdf(path, key='open') # 若一个h5文件里只有一个key,可以不写;有多个key,读取时必须指定key df.to_hdf(path, key='open') # 一个h5文件可以存储多个DataFrame,通过key来索引不同DataFrame
-
JSON
# 用到再看吧