科学计算库(二)

Pandas

Posted by 新宇 on January 25, 2020

一、Pandas

1. 介绍

2. Pandas的优势

  • 增强图表可读性
  • 便捷的数据处理能力
  • 读取文件方便
  • 封装了Matplotlib、Numpy的画图和计算

3. Pandas数据结构

1. Series

  1. Series是一个类似于一维数组的数据结构,它能够保存任何类型的数据,比如整数、字符串、浮点数等,主要由一组数据和与之相关的索引两 部分构成。

  2. 代码

     pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])
    
     # Series的属性:index和values
    
     color_count.index
     # 结果
    
     Index(['blue', 'green', 'red', 'yellow'], dtype='object')
    
     color_count.values
     # 结果
    
     array([ 200, 500, 100, 1000])
    
     color_count[2]
     # 结果 
    
     100
    	 
    

2. DataFrame

  1. DataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引;
    • 行索引,表明不同行,横向索引,叫index,0轴,axis=0
    • 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
  2. 代码
      # 生成10名同学,5门功课的数据
    
     score = np.random.randint(40, 100, (10, 5))
    
     # 使用Pandas中的数据结构 
    
     score_df = pd.DataFrame(score)
    
     # 构造行索引序列
    
     subjects = ["语文", "数学", "英语", "政治", "体育"]
     # 构造列索引序列
    
     stu = ['同学' + str(i) for i in range(score_df.shape[0])]
     # 添加行索引
    
     data = pd.DataFrame(score, columns=subjects, index=stu)
    
    
  3. 属性
     # DataFrame的属性: 
    
     # DataFrame的行索引列表
    
     data.index
     # DataFrame的列索引列表
    
     data.columns
     # 直接获取其中array的值
    	
     data.value
     # 转置
    
     data.T
     # 显示前5行内容
    
     data.head(5)
     # 显示前5行内容
    
     data.tail(5)
    
  4. DatatFrame索引的设置
     stu = ["学生_" + str(i) for i in range(score_df.shape[0])]
     # 必须整体全部修改 
    
     data.index = stu
    
     # 重设索引 eset_index(drop=False)
    
     # 默认为False,不删除原来索引,如果为True,删除原来的索引值
    
     data.reset_index(drop=True)
    
  5. 以某列值设置为新的索引
     # et_index(keys, drop=True)
    
     # keys : 列索引名成或者列索引名称的列表
    
     # drop : boolean, default True.当做新的索引,删除原来的列
    	
     df = pd.DataFrame({'month': [1, 4, 7, 10],'year': [2012, 2014, 2013, 2014],'sale':[55, 40, 84, 31]})
    
     df.set_index('month')
     # 设置多个索引,以年和月份(变成了一个具有MultiIndex的DataFrame)
    
     df = df.set_index(['year', 'month']
    

3. MultiIndex

  1. MultiIndex是多级索引(也称层次化索引是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。)三维的数据结构;

  2. 代码

     # 创建方式一:元组列表
    
     m_index1=pd.Index([("A","x1"),("A","x2"),("B","y1"),("B","y2"),("B","y3")],name=["class1","class2"])
     m_index1
     # 结果
    
     MultiIndex(levels=[['A', 'B'], ['x1', 'x2', 'y1', 'y2', 'y3']],
            labels=[[0, 0, 1, 1, 1], [0, 1, 2, 3, 4]],
            names=['class1', 'class2'])
     # 与DataFrame结合,形成二级索引
    
     df1=DataFrame(np.random.randint(1,10,(5,3)),index=m_index1)
    
     # 创建方式二:特定结构
    
     class1=["A","A","B","B"]
     class2=["x1","x2","y1","y2"]
     m_index2=pd.MultiIndex.from_arrays([class1,class2],names=["class1","class2"])
     df2=DataFrame(np.random.randint(1,10,(4,3)),index=m_index2)
    
    

4. Panel(已弃用)

4. Pandas高级操作

1. 索引

# 不支持操作

data[:3,:2]
# 错误操作: 必须先列后行

data['2018-02-27']['open']
# 正确:先列后行

data['open']['2018-02-27']

# loc 与 iloc, loc 使用索引名, iloc 使用索引下标, 此处都是先行后列, 左闭右闭
data.loc[:'2018-02-23', 'open':'low']
data.iloc[:3, :2]

# ix混合索引, 即将废弃,不建议使用

data.ix[:'2018-02-23', :2]

# 混合索引:通过 loc 获取的方式

data.loc[data.index[0:4], 'open':'low']

# 混合索引:通过 iloc 获取的方式 

data.iloc[0:4, data.columns.get_indexer(['open','low'])]

2. 赋值操作

# 对列进行赋值, 直接对原来的值进行修改

data.high = 10
data['high'] = 1

3. 排序

# 排序有两种形式,一种对于索引进行排序,一种对于内容进行排序

# 对索引进行排序 axis=0 行索引排序,axis=1 列索引排序

data.sort_index(axis=1).head() 

# 对于内容进行排序 , ascending 是否升序排列

data['open'].sort_values(ascending=False).head()

4. 运算

  1. 加减法运算

     # 比如进行数学运算加上具体的一个数字
    
     data['open'].add(10).head()
     # 减法运算
    
     data['open'].sub(10).head()
    
  2. 逻辑运算

     #  & 与, | 或
    
     data[(data["open"] > 23.19) & (data["open"] < 23.21)].head()
    
  3. 统计运算

     # 综合分析: 能够直接得出很多统计结果, count , mean , std , min , max 等
    
     data.describe()
    
    
     # 使用统计函数: 0 代表列求结果, 1 代表行求统计结果
    
     data.max(0)
    
     # 求中位数 ,分两步: 1 先对列进行排序 2 找中间值,如果有两个则取平均数
    
     df.median(0)
    
     # idxmax()/ idxmin(): 求出最大/小值的位置
    
     data.idxmax(axis=0)
    
     # 累计统计函数 cumsum()
    
     stock_rise = data['p_change']
     stock_rise.head()
     stock_rise.cumsum()
     # 使用pandas绘图
    
     stock_rise.cumsum().plot()
     plt.show()
    
    
     # 自定义运算
    
     data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=1)
    

5. 画图

  • pandas.DataFrame.plot
    • line : line plot (default)
    • bar : vertical bar plot
    • barh : horizontal bar plot
    • hist : histogram
    • pie : pie plot
    • scatter : scatter plot
    • 更多细节
  • pandas.Series.plot

6. 文件读取与存储

# 读CSV

stock = pd.read_csv('./data/stock_day.csv')
# 写CSV

stock_1.to_csv('./data/stock_test.csv', columns=['open'], index=False)

# 读HDF5, 需要指定键的名字

day_close = pd.read_hdf("./data/day_close.h5", key='day_close')
# 写HDF5

day_close_1 = day_close.iloc[:3,:2]

# 写HDF5

day_close_1.to_hdf('./data/day_close.h5', key='day_close_1')
# 导入h5py,查看keys 

import h5py 

f=h5py.File("./data/day_close_test.h5","r")
for i in f.keys():
    print(i)

# 读json 
# orient: 输出格式,可选值 split,records,index,columns,values
# lines : 是否按照每行读取json对象

json = pd.read_json('./data/Sarcasm_Headlines_Dataset.json', orient='records', lines=True)
# 写json

json.to_json("./data/Sarcasm_Headlines_Dataset_test.json", orient="records",lines=True)

7. 缺失值处理

  • 如果缺失值的标记方式是NaN
    • 判断数据中是否包含NaN:
      • pd.isnull(df),
      • pd.notnull(df)
    • 存在缺失值nan:
      • 1、删除存在缺失值的:dropna(axis=’rows’)
        • 注:不会修改原数据,需要接受返回值
      • 2、替换缺失值:fillna(value, inplace=True)
        • value:替换成的值
        • inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象
  • 如果缺失值没有使用NaN标记,比如使用”?”
    • 先替换‘?’为np.nan,然后继续处理
# 1.判断缺失值是否存在

if np.all(pd.notnull(movie)) == False:
# 或者

if np.any(pd.isnull(movie)) == True:

# 2.删除缺失值,使用dropna,(前提是,缺失值的类型必须是np.nan)

# 不修改原数据 

movie.dropna()
# 可以定义新的变量接受或者用原来的变量名 

data = movie.dropna()

# 3.替换缺省值

for i in movie.columns:
	if np.all(pd.notnull(movie[i])) == False:
		print(i)
		movie[i].fillna(movie[i].mean(), inplace=True)

# 4.当缺省值不是NaN

# 把一些其它值标记的缺失值,替换成np.nan

wis = wis.replace(to_replace='?', value=np.nan)

8.数据离散化

  1. 为什么要离散化?

    连续属性离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。

  2. 什么是数据的离散化?

    连续属性的离散化就是在连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。

  3. 举个例子: 离散化有很多种方法,这使用一种最简单的方式去操作 原始人的身高数据:165,174,160,180,159,163,192,184 假设按照身高分几个区间段:150~165, 165~180,180~195 这样我们将数据分到了三个区间段,我可以对应的标记为矮、中、高三个类别,最终要处理成一个”哑变量”矩阵

  4. 离散化方法:
    • pd.qcut(data, q):
      • 对数据进行分组将数据分组,一般会与value_counts搭配使用,统计每组的个数
    • series.value_counts():
      • 统计分组次数
  5. 代码:
     # 自行分组
    
     qcut = pd.qcut(p_change, 10) 
     # 计算分到每个组数据个数 
    
     qcut.value_counts()
    
     # 自己指定分组区间
    
     bins = [-100, -7, -5, -3, 0, 3, 5, 7, 100] 
     p_counts = pd.cut(p_change, bins)
    
  6. one-hot编码(独热编码)

     # 得出one-hot编码矩阵
    
     dummies = pd.get_dummies(p_counts, prefix="rise")
    

9.数据合并

  • pd.concat: 按照行或列进行合并,axis=0为列索引,axis=1为行索引
    • pd.concat([data1, data2], axis=1)
  • pd.merge: 可以指定按照两组数据的共同键值对合并或者左右各自
    • pd.merge(left, right, how=’inner’, on=None)
    • left : DataFrame
    • right : 另一个DataFrame on : 指定的共同键
    • how: 按照什么方式连接(内外左右)

10. 交叉表与透视表

  • 交叉表: 交叉表用于计算一列数据对于另外一列数据的分组个数(用于统计分组频率的特殊透视表)
    • pd.crosstab(value1, value2) 交叉表
  • 透视表: 透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数
    • data.pivot_table()
    • DataFrame.pivot_table([], index=[]) 透视表≤

11. 分组与聚合

  1. 什么是分组与聚合?

  2. 分组、聚合API
    • DataFrame.groupby(key, as_index=False)
      • key:分组的列数据,可以多个
    • sum、count等聚合函数
      • 聚合和分组必须一块出现
  3. 代码(统计星巴克店面数量)

     # 导入星巴克店的数据
    
     starbucks = pd.read_csv("./data/starbucks/directory.csv")
     # 按照国家分组,求出每个国家的星巴克零售店数量 
    
     count = starbucks.groupby(['Country']).count()
     count['Brand'].plot(kind='bar', figsize=(20, 8)) 
     plt.show()