机器学习之Pandas教程(上)
1. 教程简介
本教程分为上、下两节,主要针对机器学习数据处理做的简单教程。本教程主要不是讲解pandas函数的使用,而是实验性的操作学习方式,对于使用本教程的学者,可以根据课程一步一步去实验,对于不懂的函数以及实现方式可以在官网进行查询。注意,重点还是动手自己操作。
2. Pandas简介
pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。pandas有三种数据结构形式,分别是Series,DataFrame和索引对象。本教程上节也主要是讲解着几种结构形式,下节讲解pandas在特征工程中常用的操作。
3. Series结构
3.1 构造和初始化Series
import pandas as pdimport numpy as np
3.1.1 通过list来构建
# Series是一个一维的数据结构,下面是一些初始化Series的方法s = pd.Series([5, 9, "shanghai","shenzhen",7,5.2])s
输出:
# 切片读取s[1:3]
输出:
# pandas会默认用0到n-1来作为Series的index,但是我们也可以自己指定index。index我们可以把它理解为dict里面的key。s = pd.Series([5, 9, "shanghai","shenzhen",5.2],index=["A", "B", "C", "D", "E"])s
输出:
# 通过制定的key获取元素s["C"]
输出: 'shanghai'
3.1.2 通过dictionary来构建
cities = {"Shanghai": 90000, "Foshan": 4500, "Dongguan": 5500, "Beijing": 6600, "Nanjing": 8000, "Lanzhou": None}apts = pd.Series(cities, name="price")apts
输出:
3.1.2 通过numpy ndarray来构建
s = pd.Series(np.random.randn(6), index=list("abcdef"))s
输出:
3.2 数据的选择
对于Series我们可以向list一样进行元素的获取。
3.2.1 通过list方式
cities = {"Shanghai": 90000, "Foshan": 4500, "Dongguan": 5500, "Beijing": 6600, "Nanjing": 8000, "Lanzhou": None}apts = pd.Series(cities, name="price")# 获取元素 list方式apts[[4,3,2]]
输出:
3.2.2 通过切片方式
# 切片方式apts[3:]
输出:
# 切片方式 :-2表示从0到末尾第二个apts[:-2]
输出:
# 读取到倒数第一个apts[:-1]
输出:
# 从第一个到最后一个apts[1:]
输出:
3.2.2 通过key获取
# 通过key获取,前面定义的index就是用来选择数据的apts["Shanghai"]
输出:90000.0
# 通过key组成的list获取元素,对于Series没有的就返回空apts[["Shenzhen", "Nanjing", "Dongguan"]]
输出:
3.2.3 判断元素是否存在
"Shanghai" in apts
输出:True
"Chongqing" in apts
输出:False
3.2.4 用get读取元素
# 用读取元素,当Series中没有这个元素时,可以返回我们制定的数,这里定义为0apts.get("Shanghai", 0)
输出:90000.0
# apts中没有Shenzhenapts.get("Shenzhen", 0)
输出:0
3.2.5 用过bool类型获取元素
#获取小于7000的元素apts[apts < 7000]
输出:
# 返回大于平均值的数apts[apts > apts.median()]
输出:
# 具体的过程less_than_7000 = apts < 50000less_than_7000
输出:
apts[less_than_7000]
输出:
3.3 Series元素赋值
对于Series赋值非常简单,对于以上我们已经拿到了Series,那我们可以直接对其赋值就可以。
apts["Shanghai"] = 68000apts
输出:
# 小于50000的都赋值给60000apts[apts < 50000] = 60000apts
输出:
3.4 Series数学运算
# 每个元素都乘上2apts * 2
输出:
# 每个元素都除于2apts / 2
输出:
# 每个元素都加上10000,但是对于值为NAN的元素你做运算apts + 10000
输出:
# 平方运算apts ** 2
输出:
# 开根号np.square(apts)
输出:
3.5 缺损值处理
# 判断哪个值不是NaNapts.notnull()
输出:
# 判断是否有NaNapts.isnull()
输出:
# 对缺损值进行填充apts[apts.isnull()] = apts.mean()apts
输出:
4. Dataframe结构
Dataframe就像是一张表格,而Series表示的是一个以为数组,Dataframe则是一个二维数组,可以类比成一张Excel表格,而是Dataframe的一行或者一列则是一个Series。对于Dataframe的行用index表示,列用columns表示。
4.1 Dataframe的创建
4.1.1 通过dictionary创建
dataframe可以是有一个dictionary构造来创建。
data = {'city': ['Shanghai', 'Nanjing', 'Lanzhou', 'Shangsha', 'Guizhou', 'Xian'],'year': [2017,2018,2017,2018,2018,2017],'population': [2100, 600, 800, 700, 560, 900]}pd.DataFrame(data)
输出:
# 可以指定columns的名字和顺序pd.DataFrame(data, columns=["year", "city", "population"])
输出:
# 创建时指定index和columnsframe = pd.DataFrame(data, columns=["year", "city", "population", "debt"],index=["one", "two", "three", "four", "five", "six"])frame
输出:
4.1.2 通过Series创建
cars = pd.Series({"Beijing": 300000, "Shanghai": 350000, "Shenzhen": 300000, "Tianjian": 200000, "Guangzhou": 250000, "Chongqing": 150000})cities = {"Shanghai": 90000, "Foshan": 4500, "Dongguan": 5500, "Beijing": 6600, "Nanjing": 8000, "Lanzhou": None}apts = pd.Series(cities, name="price")df = pd.DataFrame({"apts": apts, "cars": cars})df
输出:
4.1.3 通过dicts的list来构建Dataframe
data = [{"Beijing": 1000, "Shanghai": 2500, "Nanjing": 9850}, {"Beijing": 5000, "Shanghai": 4600, "Nanjing": 7000}]pd.DataFrame(data)
输出:
# 定义indexdata = [{"Beijing": 1000, "Shanghai": 2500, "Nanjing": 9850}, {"Beijing": 5000, "Shanghai": 4600, "Nanjing": 7000}]pd.DataFrame(data, index=["salary", "other"])
输出:
4.2 获取Dataframe的值
4.2.1 通过列名的方式
# 通过列名frame["city"]
输出:
# 也可以用这种方式,与上面的效果一样frame.year
输出:
# 判断类型type(frame.year)
输出:pandas.core.series.Series
4.2.2 通过loc函数
# 通过自己定义的index获取frame.loc["three"]
输出:
# 通过行列名字或者frame.loc["three", "city"]
输出:Lanzhou
4.2.2 通过iloc函数
通过iloc方法可以拿到行和列,直接按照index的顺序来取。可以当做numpy的ndarray的二维数组来操作。
# 获取前三行frame.iloc[0:3]
输出:
# 切片操作frame.iloc[0:3, 1:3]
输出:
4.3 Dataframe赋值
对于以上获取到Dataframe以后,要想对其赋值是很简单的。
frame.loc["one", "population"] = 5555frame
输出:
# 给一整列赋值frame["debt"] = 1000frame
输出:
# 对整行赋值frame.loc["six"] = np.NaNframe
输出:
4.4 获取columns和index
# 获取columns名frame.columns
输出:Index(['year', 'city', 'population', 'debt'], dtype='object')
# 获取index名frame.index
输出:Index(['one', 'two', 'three', 'four', 'five', 'six'], dtype='object')
# 输出columns名for name in frame.columns:print(name)
输出:
4.5 用Series指定Dataframe要修改的值
用Series来指定需要修改的index以及相应的value,没有指定的默认用NaN。
val = pd.Series([100, 200, 300], index=['two', 'three', 'four'])frame["debt"] = val * 1000frame
输出:
4.6 给index与columns指定名字
frame.index.name = "row"frame.columns.name = "columns"frame
输出:
4.6 把Dataframe转换成ndarray
有时候某些操作需要对数据进行装换numpy.ndarray类型才能进行处理,所以要用values对Dataframe进行转换或者as_matrix函数。
df.values
输出:
# 判定类型type(df.values)
输出:numpy.ndarray
# 另一个方法df.as_matrix()
输出:
4.7 Dataframe删除操作
data = DataFrame(np.arange(16).reshape((4,4)),index = ['Ohio','Colorado','Utah','New York'],columns = ['one','two','three','four'])print(data)#放一个标量就删除一行或一列,放一个数组就删除一组行或者一组列print(data.drop(['Colorado','Ohio']))#axis=0:从上到下,沿着行的方向操作,axis=1:从左到右,沿着列的方向操作print(data.drop('two',axis=1))print(data.drop(['two','four'],axis=1))
输出:
4.8 统计描述
df = DataFrame([[1.4, np.nan], [7.1, -4.5], [np.nan, np.nan], [0.75, -1.3]],index=['a', 'b', 'c', 'd'],columns=['one', 'two'])print(df)# 每一列的统计信息(自己尝试一下非数值型变量统计结果是什么?)df.describe()
输出:
# get index objectobj = pd.Series(range(3), index=["a", "b", "c"])index = obj.indexindex
5. index
5.1 index object
obj = pd.Series([4.5, 2.6, -1.8, 9.4], index=["d", "b", "a", "c"])obj
输出:Index(['a', 'b', 'c'], dtype='object')
5.2 index 一些操作
# 获取index元素index[1:]
输出:Index(['b', 'c'], dtype='object')
# index的值是不能被更改的# index[0] = 6
# 构造indexindex = pd.Index(np.arange(3))index
输出:Int64Index([0, 1, 2], dtype='int64')
# index的使用obj2 = pd.Series([2,5,7], index=index)obj2
输出:
# 判断index元素obj2.index is index
输出:True
# 注意与上面的区别obj2.index is np.arange(3)
输出:False
obj2.index == np.arange(3)
输出:array([ True, True, True], dtype=bool)
# 判断index是否存在pop = {'Nanjing': {2017: 1000, 2018:1100},'Guangzhou': {2016:800, 2017:850, 2018:880}}frame3 = pd.DataFrame(pop)print(frame3)print("Shanghai" in frame3.columns)
输出:
2017 in frame3.index
输出:True
5.3 index 索引与切片
# 索引,按照index的元素进行索引obj = pd.Series(range(3), index=["a", "b", "c"])obj["a"]
输出:0
# 使用index默认的数字进行索引obj[[1,2]]
输出:
# 按照bool值进行索引obj[obj<2]
输出:
# 切片方式obj["b":"c"]
输出:
obj["b":]
输出:
5.4 DataFrame 的index
cars = pd.Series({"Beijing": 300000, "Shanghai": 350000, "Shenzhen": 300000, "Tianjian": 200000, "Guangzhou": 250000, "Chongqing": 150000})cities = {"Shanghai": 90000, "Foshan": 4500, "Dongguan": 5500, "Beijing": 6600, "Nanjing": 8000, "Lanzhou": None}apts = pd.Series(cities, name="price")df = pd.DataFrame({"price": apts, "cars": cars})df
输出:
# 通过index获取元素,没有的列输出NaNdf.loc["Beijing":"Guangzhou", ["price", "other"]]
输出:
# 切片获取df.iloc[2:4, 1:3]
输出:
注:loc与iloc的区别,loc可以用名字进行选择,iloc用index数字进行选择
5.4 DataFrame 条件选择
5.4 DataFrame 的index
输出:
# 条件选择df[df.price > 5000]
输出:
5.5 Series index重排
把一个Series或者DataFrame按照新的index顺序进行重排
obj = pd.Series([4.5, 2.6, -1.8, 9.4], index=["d", "b", "a", "c"])obj
输出:
# 对index进行重排obj.reindex(["a", "b", "c", "d", "e"])
输出:
5.6 Series reindex对NaN进行填充
把一个Series或者DataFrame按照新的index顺序进行重排
obj.reindex(["a", "b", "c", "d", "e"], fill_value=obj.mean())
输出:
# 如果为空,填充前面index的值obj3.reindex(range(6), method="ffill")
输出:
# 获取后面的值,进行填充obj3.reindex(range(6), method="bfill") # backward fill
输出:
5.7 DataFrame index重排
data = {'city': ['Shanghai', 'Nanjing', 'Lanzhou', 'Shangsha', 'Guizhou', 'Xian'],'year': [2017,2018,2017,2018,2018,2017],'population': [2100, 600, 800, 700, 560, 900]}frame = pd.DataFrame(data, columns=["year", "city", "population", "debt"],index=["one", "two", "three", "four", "five", "six"])frame2 = frame.reindex(["one", "three", "four", "eight"])frame2
输出:
# 对列进行重排frame.reindex(columns=["city", "year", "population"])
输出:
5.8 对index进行删除
对于使用drop删除index并不能真正,只是删除之后,返回剩余的部分。
obj3 = pd.Series(["blue", "red", "yello"], index=[1,3,5])obj4 = obj3.drop(5)print(obj4)obj3
输出:
obj3.drop([3,5])
输出:
# 对dataframe进行dropdata = {'city': ['Shanghai', 'Nanjing', 'Lanzhou', 'Shangsha', 'Guizhou', 'Xian'],'year': [2017,2018,2017,2018,2018,2017],'population': [2100, 600, 800, 700, 560, 900]}frame = pd.DataFrame(data, columns=["year", "city", "population", "debt"],index=["one", "two", "three", "four", "five", "six"])frame.drop(["debt", "year"], axis=1)
输出:
5.8 Series多层index
# Series的多层index# 构造多层indexdata = pd.Series(np.random.randn(10), index= [['a','a','a','b','b','c','c','c','d','d'], [1,2,3,1,2,1,2,3,1,2]])print(data)
输出:
# 获取index objectdata.index
输出:
# 通过index获取元素data.b
输出:
# 切片方式data["b":"c"]
输出:
# 通过默认的indexdata[2:5]
输出:
5.9 hierarchical indexing和DataFrame转换
可以通过unstack和stack进行转换。
type(data.unstack())
输出:data.unstack().stack()
data.unstack().stack()
输出:
5.10 hierarchical indexing & DataFrame
frame = pd.DataFrame(np.arange(12).reshape((4,3)),index = [['a','a','b','b'], [1,2,1,2]],columns = [['xiaoming', 'lisi', 'lisi'], ['one', 'tow', 'three']])frame
输出:
# 取值frame.loc["a", 1]["lisi"]["tow"]
输出:1
6. CSV文件读取
6.1 默认读取方式
goog = pd.read_csv("data/GOOG.csv")goog.head() #输出前几个
输出:
6.2 指定index读取
# 读进来的时候设置index,声明哪里列是日期goog = pd.read_csv("data/GOOG.csv", index_col=0, parse_dates=[0])goog.head()
输出:
# 获取indexgoog.index
输出:'2004-08-19', '2004-08-20', '2004-08-23', '2004-08-24'..........
6.3 CSV文件存储
使用to_csv函数。
# 以\t的方式进行分隔df.to_csv("data/test.tsv", sep="\t")
6. 作图
# 根据上面的数据作图# 把图片输出到当前界面%matplotlib inlinegoog["Adj Close"].plot()
输出:
# 1/1/2010", periods=1000):从这个日期开始,往后推一千天ts = pd.Series(np.random.randn(1000)*100, index=pd.date_range("1/1/2010", periods=1000))ts = ts.cumsum()ts.plot()
输出:
# dataframe直接绘制图像df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list("ABCD"))df = df.cumsum()df.plot()
输出:
# 绘制柱状图df.iloc[5].plot(kind="bar")
输出:
# 状图图# 横着画df.head().plot.barh(stacked=True)# 竖着 画# df.head().plot.bar(stacked=True)
输出:
对于机器学习之pandas的应用上节到这里结束了,对于跟着这个教程学习的同学,一定要多操作,多动手。