目录
一、引入Pandas进行数据处理的必要性
NumPy 通过把大量同类数据组织成 ndarray 数组对象,并引入可以支持逐元素操作和广播机制的通用函数,为数值计算提供了许多不可或缺的功能。但当需要处理更灵活的数据任务(如为数据添加标签、处理缺失值等),或者需要做一些不是对每个元素都进行广播映射的计算(如分组、透视表等)时,NumPy 的限制就非常明显了。
建立在 NumPy 数组结构上的 Pandas 库,为常见的各种数据处理任务提供了捷径。Pandas 有三个基本对象:Series、DataFrame 和 Index。其中,Series 和 DataFrame 是 Pandas 中最常用的两个对象,分别对应于一维和二维数据的处理(Pandas 还有对三维甚至多维数据处理的 Panel 对象,但不太常用)。而 Index 对象则用于为数据建立索引以方便数据操作。
Pandas(Python Data Analysis Library)是基于是基于 NumPy 的数据分析模块,它提供了大量标准数据模型和高效操作大型数据集所需的工具,可以说 Pandas 是使得 Python 能够成为高效且强大的数据分析环境的重要因素之一。
Pandas 的三种数据结构:Series、DataFrame 和 Panel。Series 类似于一维数组;DataFrame 是类似表格的二维数组;Panel 可以视为 Excel 的多表单 Sheet。
导入方式:import pandas as pd
# 引入Numpy和Pandas库
import numpy as np
import pandas as pd
二、创建Series对象
Series 对象是一个带索引的一维数组,可以基于以下对象来创建:
Python列表、Python字典、一维ndarray数组对象、甚至一个标量
(一)通过列表创建Series
基于列表创建,索引是从0开始的整数,这属于隐式索引——自动添加的整数索引。
# 基于列表创建
data = pd.Series([0.25, 0.5, 0.75, 1.0])
data
输出结果:
0 0.25
1 0.50
2 0.75
3 1.00
dtype: float64
(二)通过字典创建Series
基于字典创建,索引是排好序的字典的键,也属于隐式索引——字典的键作为索引。
# 基于字典创建
score = pd.Series({'s03':87,'s02':68,'s01':92})
score
注意:字典的键值对是无序的,但 Series 对象的索引是有序的!
输出结果:
s01 92
s02 68
s03 87
dtype: int64
(三)通过一维数组创建Series
基于一维数组创建,创建的同时可以指定索引,显式索引——明确用index
参数指定索引。
# 基于一维数组创建
rd = pd.Series(np.random.randint(0,10,5),index=['a','b','c','d','c'])
rd
注意:索引由有序、允许重复并且不可变的数据构成!
输出结果:
a 2
b 8
c 9
d 2
c 9
dtype: int32
(四)通过一个标量创建Series
基于一个标量创建,该标量会重复填充到每个索引上。
# 基于一个标量创建
pd.Series(5,index=[100,200,300])
说明 Series 元素的个数是由索引个数而非数据的个数决定的。
输出结果:
100 5
200 5
300 5
dtype: int64
(五)pd.Series函数的原型
pd.Series(data=None, index=None, dtype=None, name=None, copy=False)
参数说明:
- data:提供数据的列表、字典、一维数组或单个标量。
- index:允许指定索引。如果不指定就用从0开始的整数作为隐式索引(或位置索引),指定了就是显式索引(或标签索引);注意:索引由有序、允许重复并且不可变的数据构成!
- dtype:允许指定元素类型。如果元素类型不一致,则会统一转化成 object 类型。
1、创建时如果是不同类型的数据,则会统一转化为 object 类型
# 创建时如果是不同类型的数据,则会统一转化为object类型
tp1 = pd.Series([0.25, '0.5', 0.75, 1.0])
tp1
输出结果:
0 0.25
1 0.5
2 0.75
3 1
dtype: object
2、创建时如果与dtype参数指定的类型不一致,可能存在类型转换
# 创建时如果与dtype参数指定的类型不一致,可能存在类型转换
tp2 = pd.Series([0.25, '0.5', 0.75, 1.0], dtype='float64')
tp2
输出结果:
0 0.25
1 0.50
2 0.75
3 1.00
dtype: float64
三、Series对象的属性
每个 Series 对象由两个数组构成:
- index数组:它是从 ndarray 数组继承的 Index 索引对象,保存索引信息。
- values:保存元素值的 ndarray 数组。
1、位置索引
data.index # 位置索引
输出结果:
RangeIndex(start=0, stop=4, step=1)
data.values
输出结果:
array([ 0.25, 0.5 , 0.75, 1. ])
2、标签索引,注意字符串被表示成了object类型
score.index # 标签索引,注意字符串被表示成了object类型
输出结果:
Index(['s01', 's02', 's03'], dtype='object')
score.values
输出结果:
array([92, 68, 87], dtype=int64)
最好使用标签索引而非位置索引,前者属于显式索引,后者是隐式索引。
Python 之禅第二条:显式优于隐式(Explicit is better than implicit
)!
# import this查看Python之禅的内容
import this
输出结果:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
还可以对 Series 对象和 Index 对象分别命名,例如:
score.name = 'score of students'
score.index.name = 'sno'
score
输出结果:
sno
s01 92
s02 68
s03 87
Name: score of students, dtype: int64
四、Series对象的基本操作
(一)Series对象看作一维的Numpy数组
基于位置索引的切片,不包含终值;基于标签索引的切片,包含终值。
print(data[2]) # 用位置索引访问单个元素
print(score['s02']) # 用标签索引访问单个元素
print("********************")
print(score[1:2]) # 基于位置索引的切片,不包含终值
print(score['s01':'s02']) # 基于标签索引的切片,却包含终值
输出结果:
0.75
68
********************
sno
s02 68
Name: score of students, dtype: int64
sno
s01 92
s02 68
Name: score of students, dtype: int64
使用布尔数组做索引和使用花式索引(整数列表),得到的仍是Series对象。
print(score[score>85]) # 使用布尔数组做索引,得到的仍是Series对象
print(data[[2,0,1]]) # 使用花式索引(整数列表),得到的仍是Series对象
输出结果:
sno
s01 92
s03 87
Name: score of students, dtype: int64
2 0.75
0 0.25
1 0.50
dtype: float64
(二)Series对象看作特殊的字典
用键访问对应的值:字典不存在切片操作,因此切片操作是把 Series 对象看成 Numpy 而非字典。
通过键来返回 Series 的索引值,这种方法不建议,最好用score.index
属性来得到索引值。
print(score['s02']) # 用键访问对应的值(字典不存在切片操作,因此切片操作是把Series对象看成Numpy而非字典)
print(score.get('s03',0)) # 通过get函数访问键对应的值
print(list(score.items())) # 返回键值对
score.keys() # 通过键来返回Series的索引值,这种方法不建议,最好用score.index属性来得到索引值
注意:字典的values()
方法在此处不存在,要得到 Series 的数据值,应该使用score.values
属性。
输出结果:
68
87
[('s01', 92), ('s02', 68), ('s03', 87)]
Index(['s01', 's02', 's03'], dtype='object', name='sno')
只有出现在索引中的键值对才会保留在 Series 对象中。
score2 = pd.Series({'s01':72,'s02':90,'s03':83,'s04':88,'s05':69}, index=['s05','s01','s03'])
score2
注意:结果按索引指定的顺序显示,而非按索引值的排序显示。
输出结果:
s05 69
s01 72
s03 83
dtype: int64
结论:Series 对象中元素的个数和元素排列顺序完全由其索引来决定。
若把参数index
改为index=['s01','s03','s05','s06']
:
score22 = pd.Series({'s01':72,'s02':90,'s03':83,'s04':88,'s05':69}, index=['s01','s03','s05','s06'])
score22
输出结果:
s01 72.0
s03 83.0
s05 69.0
s06 NaN
dtype: float64
由此可见,当标签不存在时,默认以NaN
填充。
对两个 Series 对象运算时,Pandas 会按标签对齐元素,即标签相同的两元素进行计算。
当某一方的标签不存在时,默认以NaN
(Not a Number)填充。由于NaN
是一个特殊的浮点数,因此结果对象的元素被转换为float64
类型。自动对齐标签是一个非常有用的功能。
total = score+score2
total
输出结果:
s01 159.0
s02 NaN
s03 175.0
s05 NaN
dtype: float64
(三)Series对象的增删改
1、增加
# 增加多个值需要借助于一个新的Series对象
more = pd.Series([89,93],index=['s06','s07'])
print(more)
score2 = score2.append(more) # 注意:老版本是score2.append(more),但3.7版本之后都使用赋值语句的形式
print(score2)
# 增加一个值只要利用赋值操作即可,相当于字典的用法
score2['s08']=62
score2
输出结果:
s06 89
s07 93
dtype: int64
s01 72
s03 83
s05 69
s06 89
s07 93
dtype: int64
s01 72
s03 83
s05 69
s06 89
s07 93
s08 62
dtype: int64
2、删除
(1)使用del删除
# del直接原地删除一行
del score2['s08'] # 看成字典
print(score2)
输出结果:
s01 72
s03 83
s05 69
s06 89
s07 93
dtype: int64
(2)使用drop删除
# 更多使用drop删除,可以一次删除多行
score3 = score2.drop(['s06','s07']) # 不是原地删除,score2保持不变
print(score2)
print(score3)
score2.drop(['s06','s07'],inplace=True) # 原地删除,score2改变
print(score2)
输出结果:
s01 72
s03 83
s05 69
s06 89
s07 93
dtype: int64
s01 72
s03 83
s05 69
dtype: int64
s01 72
s03 83
s05 69
dtype: int64
3、改和查
# 改和查:需要利用索引,然后直接赋值
score2['s05'] = 80
print(score2)
print(score2.loc['s03'])
输出结果:
s01 72
s03 83
s05 80
dtype: int64
83