一、Pandas
1. 介绍
2. Pandas的优势
- 增强图表可读性
- 便捷的数据处理能力
- 读取文件方便
- 封装了Matplotlib、Numpy的画图和计算
3. Pandas数据结构
1. Series
-
Series是一个类似于一维数组的数据结构,它能够保存任何类型的数据,比如整数、字符串、浮点数等,主要由一组数据和与之相关的索引两 部分构成。
-
代码
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
- DataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引;
- 行索引,表明不同行,横向索引,叫index,0轴,axis=0
- 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
- 代码
# 生成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)
- 属性
# DataFrame的属性: # DataFrame的行索引列表 data.index # DataFrame的列索引列表 data.columns # 直接获取其中array的值 data.value # 转置 data.T # 显示前5行内容 data.head(5) # 显示前5行内容 data.tail(5)
- 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)
- 以某列值设置为新的索引
# 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
-
MultiIndex是多级索引(也称层次化索引是pandas的重要功能,可以在Series、DataFrame对象上拥有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. 运算
-
加减法运算
# 比如进行数学运算加上具体的一个数字 data['open'].add(10).head() # 减法运算 data['open'].sub(10).head()
-
逻辑运算
# & 与, | 或 data[(data["open"] > 23.19) & (data["open"] < 23.21)].head()
-
统计运算
# 综合分析: 能够直接得出很多统计结果, 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:不替换修改原数据,生成新的对象
- 1、删除存在缺失值的:dropna(axis=’rows’)
- 判断数据中是否包含NaN:
- 如果缺失值没有使用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.数据离散化
- 为什么要离散化?
连续属性离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。
- 什么是数据的离散化?
连续属性的离散化就是在连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。
-
举个例子: 离散化有很多种方法,这使用一种最简单的方式去操作 原始人的身高数据:165,174,160,180,159,163,192,184 假设按照身高分几个区间段:150~165, 165~180,180~195 这样我们将数据分到了三个区间段,我可以对应的标记为矮、中、高三个类别,最终要处理成一个”哑变量”矩阵
- 离散化方法:
- pd.qcut(data, q):
- 对数据进行分组将数据分组,一般会与value_counts搭配使用,统计每组的个数
- series.value_counts():
- 统计分组次数
- pd.qcut(data, q):
- 代码:
# 自行分组 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)
-
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)
- pd.crosstab(value1, value2)
- 透视表: 透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数
- data.pivot_table()
- DataFrame.pivot_table([], index=[])
11. 分组与聚合
-
什么是分组与聚合?
- 分组、聚合API
- DataFrame.groupby(key, as_index=False)
- key:分组的列数据,可以多个
- sum、count等聚合函数
- 聚合和分组必须一块出现
- DataFrame.groupby(key, as_index=False)
-
代码(统计星巴克店面数量)
# 导入星巴克店的数据 starbucks = pd.read_csv("./data/starbucks/directory.csv") # 按照国家分组,求出每个国家的星巴克零售店数量 count = starbucks.groupby(['Country']).count() count['Brand'].plot(kind='bar', figsize=(20, 8)) plt.show()