机器学习Day2——Pandas的使用
专门用于数据挖掘的开源python库以Numpy为基础,借力Numpy模块在计算方面性能高的优势基于matplotlib,能够简便的画图具有独特的数据结构func:自定义函数axis=0:默认是列,axis = 1为行进行运算定义一个对列,最大值-最小值的函数。
本栏目为本人自学B站各位好心的博主所录视频过程中记录下来的笔记,出处基本来自于B站视频博主以及csdn中各位大佬的解释,我只起到了转载的作用。因来源过于复杂,因此无法标注来源。
此篇数据分析文章的内容均来自于Bilibili的黑马程序员的数据挖掘的课程,本人仅起到总结的作用
目录
1.pandas包
1.1 什么是pandas
- 专门用于数据挖掘的开源python库
- 以Numpy为基础,借力Numpy模块在计算方面性能高的优势
- 基于matplotlib,能够简便的画图
- 具有独特的数据结构
1.2 为什么要使用pandas
Numpy已经能够帮助我们处理数据,能够结合matplotlib解决部分数据展示等问题,那么pandas学习的目的在什么地方呢?
- 便捷的数据处理能力
- 读取文件方便
- 封装了Matplotlib、Numpy的画图和计算
1.3 DataFrame
在正式开始学习前,不妨举个易于理解的例子:
回顾学习Numpy时随机生成数组,那时的数组只是人为的赋予其含义,并未给予形式上的定义,也就是说让其他人来看,并不知道行和列各自代表着什么意思,而pandas中的DataFrame数据结构就可以生成一张带有行列含义的二维表
import numpy as np
# 创建一个符合正态分布的10个股票5天的涨跌幅数据
stock_change = np.random.normal(0, 1, (10, 5))
import pandas as pd
pd.DataFrame(stock_change)
pd.DataFrame(stock_change)的值如下所示,返回的是一个带有行列索引的二维表:
# 添加行索引
stock = ["股票{}".format(i) for i in range(10)]
pd.DataFrame(stock_change, index=stock)
# 添加列索引
date = pd.date_range(start="20180101", periods=5, freq="B")
data = pd.DataFrame(stock_change, index=stock, columns=date)
那么如今的data值为:
1.3.1 DataFrame的属性
data.shape # 返回几行几列
data.index # 返回行索引
data.columns # 返回列索引
data.values # 返回不带行列索引的二维数组
data.T # 返回转置的数组
data.head(3) # 取数组的前三条记录
data.tail(2) # 取数组的最后2条记录
1.3.2 DataFrame的行列索引的修改
- 修改行列索引
DataFrame中的行列索引并不能直接通过访问下标的形式来赋值修改。若要修改某一个值,则需要将整个行或列索引全部修改。
- 重设索引
data.reset_index(drop=False)
- 设置新索引
df = pd.DataFrame({'month': [1, 4, 7, 10],
'year': [2012, 2014, 2013, 2014],
'sale':[55, 40, 84, 31]})
# 设月为索引
df.set_index("month", drop=True)
# 设年、月为索引
new_df = df.set_index(["year", "month"])
1.4 MultiIndex与Panel
1.4.1 MultiIndex
多级或分层索引对象。
- index属性
- names:levels的名称
- levels:每个level的元组值
new_df.index
#其类型为:
MultiIndex(levels=[[2012, 2013, 2014], [1, 4, 7, 10]],
labels=[[0, 2, 1, 2], [0, 1, 2, 3]],
names=['year', 'month'])
1.4.2 Panel
已弃用
1.4.3 Series
可以简单的理解为:带索引的一维数组。
sr = data.iloc[1, :]
# sr的样式为:
2018-01-01 0.283614
2018-01-02 0.431016
2018-01-03 -0.771543
2018-01-04 0.482862
2018-01-05 -0.307247
Freq: B, Name: 股票_1, dtype: float64
sr.index
# sr.index的样式为:
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
'2018-01-05'],
dtype='datetime64[ns]', freq='B')
sr.values
# sr.values的样式为:
array([ 0.28361364, 0.43101642, -0.77154311, 0.48286211, -0.30724683])
type(sr.values)
# type(sr.values)的值为:
numpy.ndarray
pd.Series(np.arange(3, 9, 2), index=["a", "b", "c"])
# 显示效果为:
a 3
b 5
c 7
dtype: int64
1.4 基本数据操作
1.4.1 索引操作
- 直接使用行列索引(先列后行)
行列索引不一定为整形,也有可能为字符创类型 - 按名字索引
data.loc["2018-02-26", "open"]
- 按数字索引(行,列)
data.iloc[1, 0]
1.4.2 赋值操作
data.列索引 = 100
data.iloc[1,0] = 300
1.4.3 排序操作
- 对内容排序
DataFrame
- 使用df.sort_values(key=,ascending=)对内容进行排序。
- 单个键或者多个键进行排序默认升序
- ascending=False : 降序
- ascending=True : 升序
data.sort_values(by=["high", "p_change"], ascending=False)
Series
- 使用Series.sort_values(ascending=)对内容进行排序。
- ascending=False : 降序
- ascending=True : 升序
sr.sort_values(ascending=False)
- 对索引排序
DataFrame
- 使用df.sort_index对索引进行排序
data.sort_index()
Series
- 使用Series.sort_index对索引进行排序
sr.sort_index()
1.5 DataFrame运算
本部分所采用的数据节选如下:
1.5.1 算术运算
data["open"].add(3)
data.sub(100)
data["close"].sub(data["open"])
1.5.2 逻辑运算
data[data["p_change"] > 2]
data[(data["p_change"] > 2) & (data["low"] > 15)]
data.query("p_change > 2 & low > 15")
data[data["turnover"].isin([4.19, 2.39])] #判断值是否为4.19或2.39
1.5.3 统计运算
data.describe() #计算出每列的count、mean、std、min、25%、50%、75%、max
data.max(axis = 0) #0为列,1为行
data.min()
data.std()
data.idxmax() #最大值的下标
data.idxmin() #最小值的下标
...
- 累计统计函数
函数 | 作用 |
---|---|
cumsum | 计算前1/2/3/…/n个数的和 |
cummax | 计算前1/2/3/…/n个数的最大值 |
cummin | 计算前1/2/3/…/n个数的最小值 |
cumprod | 计算前1/2/3/…/n个数的积 |
data["p_change"].sort_index().cumsum().plot()
1.5.4 自定义运算
- apply(func, axis=0)
- func:自定义函数
- axis=0:默认是列,axis = 1为行进行运算
- 定义一个对列,最大值-最小值的函数
data.apply(lambda x: x.max() - x.min(), axis = 0)
1.6 DataFrame画图
- DataFrame.plot (x=None, y=None, kind=“line”)
- x : label or position, default None
- y : label,position or list of label, positions, default None
- Allows plotting of one column versus another
- kind : str
- ‘line’: line plot (default)
- ‘bar’ : vertical bar plot
- ‘barh’ : horizontal bar plot
- ‘hist’ : histogram
- ‘pie’ : pie plot
- ‘scatter’ : scatter plot
1.7 文件的读取与存储
1.7.1 CSV文件
#仅读取"high", "low", "open", "close"四列
pd.read_csv("./stock_day/stock_day.csv", usecols=["high", "low", "open", "close"])
#name字段可以为纯数据的文件数据设置表头
data = pd.read_csv("stock_day2.csv", names=["open", "high", "close", "low", "volume", "price_change", "p_change", "ma5", "ma10", "ma20", "v_ma5", "v_ma10", "v_ma20", "turnover"])
#将数据存为csv文件,读取数据中的“open”列,写入行索引,追加模式写入,写入列索引
data[:10].to_csv("D:/test.csv", columns=["open"], index=False, mode="a", header=False)
1.7.2 HDF5文件
#读取hdf5文件
day_close = pd.read_hdf("./stock_data/day/day_close.h5")
#存储hdf5形式的文件,必须要指定key的值
day_close.to_hdf("test.h5", key="close")
#再次读入hdf5形式的文件
pd.read_hdf("test.h5", key="close")
1.7.1 JSON文件
# orient以什么形式读取 lines是否按行读取
sa = pd.read_json("Sarcasm_Headlines_Dataset.json", orient="records", lines=True)
#存储为json
sa.to_json("test.json", orient="records", lines=True)
1.8 Pandas高级数据处理
1.8.1 缺失值处理
- 丢弃
- 替换或插补
- 判断数据是否为NaN :
- pd.isnull(df)或pd.notnull(df)
处理方式:
- 存在缺失值NaN ,并且是np.NaN :
- 1.删除存在缺失值的:dropna(axis=“rows”)
- 注:不会修改原数据,需要接受返回值。
- 2.替换缺失值:fillna(value, inplace=True)
- value:替换成的值
- inplace:
- True:会修改原数据
- False:不替换修改原数据,生成新的对象
- 1.删除存在缺失值的:dropna(axis=“rows”)
np.any(pd.isnull(movie)) # 返回True,说明数据中存在缺失值
np.all(pd.notnull(movie)) # 返回False,说明数据中存在缺失值
pd.isnull(movie).any() # 返回存在缺失值的字段
pd.notnull(movie).all() # 返回存在缺失值的字段
# 方法1:删除含有缺失值的样本
data1 = movie.dropna()
# 方法2:替换,用平均值替换
# 含有缺失值的字段:Revenue (Millions),Metascore
movie["Revenue (Millions)"].fillna(movie["Revenue (Millions)"].mean(), inplace=True)
movie["Metascore"].fillna(movie["Metascore"].mean(), inplace=True)
-
不是缺失值NaN ,有默认标记的
即数据不表示为NaN,而是表示为特殊标记,如?的数据。- 1.替换?为NaN
- 2.处理NaN数据
# 1)替换
data_new = data.replace(to_replace="?", value=np.nan)
# 2)删除缺失值
data_new.dropna(inplace=True)
1.8.2 数据离散化
连续属性的离散化就是在连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。
- 1)分组
- 自动分组sr=pd.qcut(data, bins)
- 自定义分组sr=pd.cut(data, [])
- 2)将分组好的结果转换成one-hot编码
- pd.get_dummies(sr, prefix=)
# 1)分组,自动分组
sr = pd.qcut(data, 3)
# 2)转换成one-hot编码
pd.get_dummies(sr, prefix="height")
# 1)分组,自定义分组
bins = [150, 165, 180, 195]
sr = pd.cut(data, bins)
# 2)转换成one-hot编码
pd.get_dummies(sr, prefix="身高")
1.8.3 合并
- 按方向拼接
pd.concat([stock, stock_change], axis=1) # 1为水平拼接,0为垂直拼接
- 按索引拼接
pd.merge(left, right, how="inner", on=["key1", "key2"]) #内连接
pd.merge(left, right, how="left", on=["key1", "key2"]) #左外连接
pd.merge(left, right, how="outer", on=["key1", "key2"]) #外连接
1.8.4 交叉表与透视表
- 交叉表(crosstable)
- 交叉表:交叉表用于计算一列数据对于另外一列数据的分组个数(寻找两个到之间的关系)
- pd.crosstab(value1, value2)
# 星期数据以及涨跌幅是好是坏数据
# pd.crosstab(星期数据列, 涨跌幅数据列)
# 准备星期数据列
# pandas日期类型
date = pd.to_datetime(stock.index)
stock["week"] = date.weekday
# 准备涨跌幅数据列
stock["pona"] = np.where(stock["p_change"] > 0, 1, 0)
# 交叉表,此刻得到的是频数
data = pd.crosstab(stock["week"], stock["pona"])
# 求频率
new_data = data.div(data.sum(axis=1), axis=0)
# 制成图表
new_data.plot(kind="bar", stacked=True)
- 透视表(pivot_table)
# 透视表操作
stock.pivot_table(["pona"], index=["week"])
1.8.5 分组与聚合
col =pd.DataFrame({'color': ['white','red','green','red','green'], 'object': ['pen','pencil','pencil','ashtray','pen'],'price1':[5.56,4.20,1.30,0.56,2.75],'price2':[4.75,4.12,1.60,0.75,3.15]})
# 进行分组,对颜色分组,price1进行聚合
# 1.用dataframe的方法进行分组
col.groupby(by="color")["price1"].max()
# 2.用Series的方法进行分组
col["price1"].groupby(col["color"]).max()
- 案例分析,统计每个国家及其省份的星巴克门店数量
# 1、准备数据
starbucks = pd.read_csv("directory.csv")
# 2、按照国家分组,求出每个国家的星巴克零售店数量并绘制柱状图
starbucks.groupby("Country").count()["Brand"].sort_values(ascending=False)[:10].plot(kind="bar", figsize=(20, 8), fontsize=40)
# 3、加入省市一起进行分组
starbucks.groupby(by=["Country", "State/Province"]).count()
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)