第四章 Pandas 统计分析基础
- Pandas(Python Data Analysis Library)是基于NumPy的数据分析模块,它提供了大量标准数据模型和高效操作大型数据集所需的工具。
- 可以说Pandas是使得Python能够成为高效且强大的数据分析环境的重要因素之一。
- 导入方式:import pandas as pd
4.1 Panndas 中的数据结构
Pandas 有三种数据结构: Series 、 DataFrame 和 Panel 。 Series 类似于一维数组;DataFrame是类似表格的二维数组;Panel可以视为Excel的多表单Sheet。
4.1.1 Series
Series 是一种一维数组对象,包含了一个值序列,并且包含了数据标签,称为索引(index),可通过索引来访问数组中的数据。
1)Series的创建
模板:
pd.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
import pandas as pd obj = pd.Series([1, -2, 3, -4]) print(obj)
【例4-1】通过列表创建Series
【例4-2】创建Series时指定索引
尽管创建Series指定了index参数,实际Pandas还是有隐藏的index位置信息的。所以Series有两套描述某条数据的手段:位置和标签
【例4-3】Series位置和标签的使用
import pandas as pd val = [2, 4 ,5, 6] idx1 = range(10, 14) idx2 = "hello the cruel world".split() s0 = pd.Series(val) s1 = pd.Series(val, index = idx1) t = pd.Series(val, index = idx2) print(s0.index) print(s1.index) print(t.index) print(s0[0]) print(s1[10]) print('default:', t[0], 'label:', t["hello"])
2)通过字典创建
如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series。
import pandas as pd sdata = {'Ohio':35000, 'Tesas': 71000, 'Oregon': 16000, 'Utah': 5000} obj3 = pd.Series(sdata) print(obj3)
如果只传入一个字典,则结果 Series 中的索引就是原字典的键(有序排列)。
【例4-6】键值和指定的索引不匹配
import pandas as pd sdata = {"a": 100, "b": 200, "e": 300} letter = ["a", "b", "c", "e"] obj = pd.Series(sdata, index = letter) print(obj)
对于许多应用而言,Series域重要的一个功能是:它在算术运算中会自动对齐不同索引的数据。
【例4-7】不同索引数据的自动对齐
sdata = {'Ohio': 3500, 'Teaxs':71000, 'Oregon': 16000, 'Utah': 5000} obj1 = pd.Series(sdata) states = ['California', 'Ohio', 'Oregon', 'Texas'] obj2 = pd.Series(sdata, index = states) print(obj1 + obj2)
【例4-8】Series索引的修改
obj = pd.Series([4,7,-3,2]) obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan'] print(obj)
4.1.2 DataFrame
DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。
DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共用同一个索引)。
1)DataFrame的创建
格式:pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
data = { 'name': ['张三', '李四', '王五', '小明'], 'sex': ['female', 'female', 'male', 'male'], 'year': [2001, 2001, 2003, 2002], 'city': ['北京', '上海', '广州', '北京'] } df = pd.DataFrame(data) print(df)
【例4-10】DataFrame的索引
df1 = pd.DataFrame(data, columns = ['name', 'year', 'sex', 'city']) print(df1)
【例4-11】DataFrame创建时的空缺值
df2 = pd.DataFrame(data, columns = ['name', 'year', 'sex', 'city','address']) print(df2)
【例4-12】DataFrame创建时指定列名
df3 = pd.DataFrame(data, columns = ['name', 'sex', 'year', 'city'], index = ['a', 'b', 'c', 'd']) print(df3)
2)DataFrame的属性
4.1.3 索引对象
Pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或 DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index。
【例4-13】显示DataFrame的索引和列。
print(df) print(df.index) print(df.columns)
【例4-14】DataFrame的 index。
print('name' in df.columns) print('in' in df.index)
每个索引都有一些方法和属性,它们可用于设置逻辑并回答有关该索引所包含的数据的常见问题。Index的常用方法和属性见表4-1。
方法 | 说明 |
append | 连接另一个Index对象,产生一个新的Index |
diff | 计算差集,并得到一个Index |
intersection | 计算交集 |
union | 计算并集 |
isin | 计算一个指示各值是否都包含在参数集合中的布尔型数组 |
delete | 删除索引i处的元素,并得到新的Index |
drop | 删除传入的值,并得到新的Index |
insert | 将元素插入到索引i处,并得到新的Index |
is_monotonic | 当各元素均大于等于前一个元素时,返回True |
is.unique | 当Index没有重复值时,返回True |
unique | 计算Index中唯一值的数组 |
4.1.4 查看 DaraFrame 的常用属性
DataFrame的基础属性有values、index、columns、dtypes、ndim和shape,分别可以获取DataFrame的元素、索引、列名、类型、维度和形状
4.2.1 重建索引
索引对象是无法修改的,因此,重新索引是指对索引重新排序而不是重新命名,如果某个索引值不存在的话,会引入缺失值。
obj = pd.Series([7.2, -4.3, 4.5, 3.6], index = ['b', 'a', 'd', 'c']) print(obj) obj.reindex(['a', 'b', 'c', 'd', 'e'])
对于重建索引引入的缺失值,可以利用fill_value参数填充。
【例4-18】重建索引时填充缺失值。
obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value = 0)
对于顺序数据,比如时间序列,重新索引时可能需要进行插值或填值处理,利用参数method选项可以设置: method = ‘ffill’ 或 ‘pad’,表示前向值填充 method = ‘bfill’ 或 ‘backfill’,表示后向值填充
【例4-19】缺失值的前向填充
import numpy as np obj1 = pd.Series(['blue', 'red', 'black'], index = [0, 2, 4]) obj1.reindex(np.arange(6), method = 'ffill')
4.2.2 更换索引
【例4-20】缺失值的后向填充。
obj2 = pd.Series(['blue', 'red', 'black'], index = [0, 2, 4]) obj2.reindex(np.arange(6),method = 'backfill')
对于DataFrame,reindex可以修改(行)索引、列,或两个都修改。如果仅传入一个序列,则结果中的行会重建索引。
【例4-21】DataFrame数据。
df4 = pd.DataFrame(np.arange(9).reshape(3, 3), index = ['a', 'c', 'd'], columns = ['one', 'two', 'four']) print(df4)
【例4-22】reindex操作。
df4.reindex(index = ['a', 'b', 'c', 'd'], columns = ['one', 'two', 'three', 'four'])
传入fill_value = n用n代替缺失值。
【例4-23】传入fill_value = n填充缺失值
df4.reindex(index = ['a', 'b', 'c', 'd'], columns = ['one', 'two', 'three', 'four'], fill_value = 100)
表4-2. reindex函数参数
参数 | 使用说明 |
index | 用于索引的新序列 |
method | 插值(填充)方式 |
fill_value | 缺失值替换值 |
limit | 最大填充量 |
level copy | 在Multiindex的指定级别上匹配简单索引,否则选取其子集 默认为True,无论如何都复制;如果为False,则新旧相等时就不复制 |
4.2.2 更换索引
§ 如果不希望使用默认的行索引,则可以在创建的时候通过Index参数来设置。
§ 在DataFrame数据中,如果希望将列数据作为索引,则可以通过set_index方法来实现。
【例4-24】重建索引。
df5 = df1.set_index('city') print(df5)
与set_index方法相反的方法是reset_index方法。
4.3 DataFrame 数据的查询与编辑
4.3.1 DataFrame 数据的查询
在数据分析中,选取需要的数据进行分析处理是最基本操作。在Pandas中需要通过索引完成数据的选取。
1)选取列:通过列索引或以属性的方式可以单独获取DataFrame的列数据,返回的数据类型为Series。
w1 = df5[['name', 'year']] display(w1) display(df5.select_dtypes(exclude = 'int64').head()) df5.select_dtypes(include=['int64', 'object']).head()
2) 选取行
print(df) print('显示前 2 行:\n', df[:2]) print('显示 2 - 3 两行:\n', df[1: 3])
选取通过DataFrame提供的head和tail方法可以得到多行数据,但是用这两种方法得到的数据都是从开始或者末尾获取连续的数据, 而利用sample可以随机抽取数据并显示。
head() #默认获取前5行
head(n)#获取前n行
tail()#默认获取后5行
tail(n)#获取后n行
sample(n)#随机抽取n行显示
sample(frac=0.6) #随机抽取60%的行
3)选取行和列
ü DataFrame.loc(行索引名称或条件,列索引名称)
ü DataFrame.iloc(行索引位置,列索引位置)
display(df5.loc[:,['name', 'year']]) display(df5.loc[['北京', '上海'], ['name', 'year']]) display(df5.loc[df5['year'] >= 2002, ['name', 'year']])
【例 4 - 28 】利用 iloc
选取行和列
print(df5.iloc[:,2]) print(df5.iloc[[1, 3]]) print(df5.iloc[[1, 3],[1, 2]])
DataFrame 行和列的选取还可以通过 Pandas的query 方法实现。用法:
Pandas.DataFrame.query(self,ecpr, inplace = False, **kwargs) 其中,参数 expr 是评估的查询字符串,kwargs是 dict 关键字参数。
【例 4- 29】 利用 query 查询数据
display(df5.query('year > 2001')) display(df5.query('year > 2001 & year < 2003'))
4)布尔选择
可以对DataFrame中的数据进行布尔方式选择。
【例 4 - 30】布尔选择
df5[df5['year'] == 2001]
4.3.2 DataFrame 数据的编辑
1)增加数据
增加一行直接通过append方法传入字典结构数据即可。
【例 - 31】DataFrame_增加数据
data1 = {'city':'兰州', 'name': '李红', 'year': 2005, 'sex': 'female'} df.append(data1, ignore_index = True)
增加列时,只需为要增加的列赋值即可创建一个新的列。若要指定新增列的位置,可以用insert函数。
【例 4 - 32】 增加一列并赋值
df['sorce'] = [85, 78, 96, 80] df.insert(1, 'No', ['001', '002', '003', '004']) df
2)删除数据
删除数据直接用drop方法,通过axis参数确定是删除的是行还是列。默认数据删除不修改原数据,需要在原数据删除行列需要设置参数inplace = True。
【例 4 - 33】删除数据行
print(df5.drop('广州'))
【例 4 - 34】 删除数据的列
df5.drop('sex', axis = 1, inplace = True) print(df5)
3)修改数据
修改数据时直接对选择的数据赋值即可。需要注意的是,数据修改是直接对 DataFrame 数据修改,操作无法撤销,因
此更改数据时要做好数据备份。
val = np.arange(10, 60).reshape(10, 5) col = ["ax", "bx", "cx", "dx", "ex"] idx = list("abcdefghij") df1 = pd.DataFrame(val, columns = col, index = idx) print('df1:\n', df1) print(df1[df1 > 30]) df1[df1 > 30] = 100
还可以使用replace进行数据的替换,用法如下:
DataFrame.replace(to_replace=None,value=None,inplace=False,limit=None,regex=False,method='pad')
其中主要参数to_replace表示被替换的值,value表示替换后的值。同时替换多个值时使用字典数据,如DataFrame.replace({‘B’:‘E’,‘C’:‘F’})表示将表中的B替换为E,C替换为F。
4)修改列名
Pandas通过DataFrame.rename()函数,传入需要修改列名的字典形式来修改列名。
df5.rename(columns={'no': 'number'}, inplace = True) display(df5)