一、Pandas简介
1.什么是Pandas?
Pandas的名称来自于面板数据(panel data)和Python数据分析(data analysis)。
Pandas是一个强大的分析结构化数据的工具集,基于NumPy构建,提供了高级数据结构和数据操作工具,它是使Python成为强大而高效的数据分析环境的重要因素之一。
一个强大的分析和操作大型结构化数据集所需的工具集,基础是NumPy,提供了高性能矩阵的运算,提供了大量能够快速便捷地处理数据的函数和方法
应用于数据挖掘,数据分析,提供数据清洗功能。http://pandas.pydata.org
2.导入pandas
# pd别名业界约定
>>>import pandas as pd
二、pandas的数据结构
Series
Series是一种类似于一维数组的对象,组成:
一组数据(各种NumPy数据类型),一组与之对应的索引(数据标签),索引(index)在左,数据(values)在右,索引是自动创建的
DataFrame
一个表格型的数据结构,它含有一组有序的列,每列可以是不同类型的值。DataFrame既有行索引也有列索引,数据是以二维结构存放的。类似多维数组/表格数据 (如,excel, R中的data.frame),每列数据可以是不同的类型,索引包括列索引和行索引
1.Series
1-1.通过list构建Series
>>> import pandas as pd
# 不指定索引的话,默认从0开始
>>> ser_obj=pd.Series(range(10,30))
>>>ser_obj
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
10 20
11 21
12 22
13 23
14 24
15 25
16 26
17 27
18 28
19 29
dtype: int64
>>> ser_obj.head(3) #打印前三行数据
0 10
1 11
2 12
dtype: int64
>>> print(type(ser_obj)) #打印数据类型
<class 'pandas.core.series.Series'>
1-2. 通过dict构建Series
>>> dict = {1000:"hello",2000:"world",3000:"!"}
>>> ser_obj = pd.Series(dict)
>>> print(ser_obj)
1000 hello
2000 world
3000 !
dtype: object
1-3.获取数据和索引
ser_obj.index 和 ser_obj.values
# 获取数据
>>> print(ser_obj.values)
['hello' 'world' '!']
# 获取索引
>>> print(ser_obj.index)
Int64Index([1000, 2000, 3000], dtype='int64')
1-4. 通过索引获取数据
ser_obj[idx]
#通过索引获取数据
>>> print(ser_obj[1000])
hello
>>> print(ser_obj[2000])
world
1-5. 设置名称
对象名:ser_obj.name 给整个表取名字
对象索引名:ser_obj.index.name 给某一列
>>> ser_obj.name = 'presidential_polls'
>>> ser_obj.index.name = 'adjpoll_trump'
>>> print(ser_obj.head())
adjpoll_trump
1000 hello
2000 world
3000 !
Name: presidential_polls, dtype: object
2.DataFrame
2-1. 通过darray构建DataFrame
>>> arr_obj = np.random.rand(3,4)
>>> df_obj = pd.DataFrame(arr_obj)
>>> print(df_obj)
0 1 2 3
0 0.471906 0.210490 0.781181 0.215866
1 0.293406 0.387063 0.961384 0.935796
2 0.761027 0.038050 0.759989 0.831180
>>> print(df_obj.head(2)) # 查看前两行
0 1 2 3
0 0.471906 0.210490 0.781181 0.215866
1 0.293406 0.387063 0.961384 0.935796
2-2. 通过dict构建DataFrame
>>> dict = {
... "A":1,
... "B":pd.Timestamp("20171212"),
... "C":pd.Series(range(10,14),dtype="float64"),
... "D":["python","java","c++","c"],
... "E":np.array([3] *4,dtype="int32"),
... "F":"Lyh"
... }
>>> df_obj = pd.DataFrame(dict)
>>> print(df_obj)
A B C D E F
0 1 2017-12-12 10.0 python 3 Lyh
1 1 2017-12-12 11.0 java 3 Lyh
2 1 2017-12-12 12.0 c++ 3 Lyh
3 1 2017-12-12 13.0 c 3 Lyh
2-3. 通过列索引获取列数据
df_obj[col_idx] 或 df_obj.col_idx
>>> print(df_obj['A'])
0 1
1 1
2 1
3 1
Name: A, dtype: int64
>>> print(type(df_obj['A']))
<class 'pandas.core.series.Series'>
>>> print(df_obj.A)
0 1
1 1
2 1
3 1
Name: A, dtype: int64
dataframe数据访问
#通过索引,先列后行
>>> print(df_obj['D'][0])
python
#查找指定元素,先找列,在找行
>>> print(df_obj.D[2])
c++
2-4. 增加列数据
df_obj[new_col_idx] = data
类似Python的 dict添加key-value
>>> df_obj["G"] = "呵呵"
>>> print(df_obj)
A B C D E F G
0 1 2017-12-12 10.0 python 3 Lyh 呵呵
1 1 2017-12-12 11.0 java 3 Lyh 呵呵
2 1 2017-12-12 12.0 c++ 3 Lyh 呵呵
3 1 2017-12-12 13.0 c 3 Lyh 呵呵
df_obj[new_col_idx] = data
类似Python的 dict添加key-value
#新增一列,数据可以是dataFrame对象的其他列运算后的结果,例如,添加H列,C的值加10
>>> df_obj["H"] = df_obj["C"]+10
>>> print(df_obj)
A B C D E F G H
0 1 2017-12-12 10.0 python 3 Lyh 呵呵 20.0
1 1 2017-12-12 11.0 java 3 Lyh 呵呵 21.0
2 1 2017-12-12 12.0 c++ 3 Lyh 呵呵 22.0
3 1 2017-12-12 13.0 c 3 Lyh 呵呵 23.0
2-5. 删除列
del df_obj[col_idx]
#通过del方法,删除指定一列的数据
>>> del(df_obj['G'] )
>>> print(df_obj.head())
A B C D E F H
0 1 2017-12-12 10.0 python 3 Qiku 20.0
1 1 2017-12-12 11.0 java 3 Qiku 21.0
2 1 2017-12-12 12.0 c++ 3 Qiku 22.0
3 1 2017-12-12 13.0 c 3 Qiku 23.0
三、Pandas的索引操作
Series和DataFrame中的索引都是Index对象
索引对象不可变,保证了数据的安全
>>> print(type(ser_obj.index))
<class 'pandas.core.indexes.numeric.Int64Index'>
>>> print(type(df_obj.index))
<class 'pandas.core.indexes.range.RangeIndex'>
常见的Index种类
Index,索引
Int64Index,整数索引
MultiIndex,层级索引
DatetimeIndex,时间戳类型
1-1. index 指定行索引名
不指定索引的话,默认从0开始
>>> ser_obj = pd.Series(range(5), index = ['a', 'b', 'c', 'd', 'e'])
>>> print(ser_obj.head())
a 0
b 1
c 2
d 3
e 4
dtype: int64
1-2. 行索引
ser_obj[‘label’], ser_obj[pos]
# 行索引
>>> print(ser_obj['b'])
1
>>> print(ser_obj[2])
2
1-3. 切片索引
ser_obj[2:4], ser_obj[‘label1’: ’label3’]
注意,按索引名切片操作时,是包含终止索引的。
>>> print(ser_obj[1:3])
b 1
c 2
dtype: int64
>>> print(ser_obj['b':'d'])
b 1
c 2
d 3
dtype: int64
1-4. 不连续索引
ser_obj[[‘label1’, ’label2’, ‘label3’]]
>>> print(ser_obj[[0, 2, 4]])
a 0
c 2
e 4
dtype: int64
>>> print(ser_obj[['a', 'e']])
a 0
e 4
dtype: int64
1-5. 布尔索引
>>> ser_bool = ser_obj > 2
>>> print(ser_bool)
a False
b False
c False
d True
e True
dtype: bool
>>> print(ser_obj[ser_bool])
d 3
e 4
dtype: int64
>>> print(ser_obj[ser_obj > 2])
d 3
e 4
dtype: int64
2-1. columns 指定列索引名
>>> df_obj = pd.DataFrame(np.random.randn(5,4), columns = ['a', 'b', 'c', 'd'])
>>> print(df_obj.head())
a b c d
0 1.201658 0.347192 1.371074 -0.111690
1 0.128548 -0.095751 0.415483 0.152507
2 1.927686 0.124433 1.118890 0.031276
3 -1.281139 -0.532217 0.074102 -0.720960
4 -0.290666 -1.252714 0.191163 0.512178
2-2. 列索引
df_obj[['label']]
>>> print(df_obj['a']) # 返回Series类型
0 1.201658
1 0.128548
2 1.927686
3 -1.281139
4 -0.290666
Name: a, dtype: float64
2-3. 不连续索引
>>> print(df_obj)
a b c d
0 1.201658 0.347192 1.371074 -0.111690
1 0.128548 -0.095751 0.415483 0.152507
2 1.927686 0.124433 1.118890 0.031276
3 -1.281139 -0.532217 0.074102 -0.720960
4 -0.290666 -1.252714 0.191163 0.512178
>>> print(df_obj[['a','c']])
a c
0 1.201658 1.371074
1 0.128548 0.415483
2 1.927686 1.118890
3 -1.281139 0.074102
4 -0.290666 0.191163
>>> print(df_obj[[1,3]])
3.高级索引:标签、位置和混合
高级索引有三种:标签,位置,混合
3-1. loc 标签索引
loc是基于标签名的索引,也就是我们自定义的索引名
# Series
>>> print(ser_obj)
a 0
b 1
c 2
d 3
e 4
dtype: int64
>>> print(ser_obj['b':'d'])
b 1
c 2
d 3
dtype: int64
>>> print(ser_obj.loc['b':'d'])
b 1
c 2
d 3
dtype: int64
3-2.DataFrame 不能直接切片,可以通过loc来做切片
# DataFrame
>>> print(df_obj)
a b c d
0 1.201658 0.347192 1.371074 -0.111690
1 0.128548 -0.095751 0.415483 0.152507
2 1.927686 0.124433 1.118890 0.031276
3 -1.281139 -0.532217 0.074102 -0.720960
4 -0.290666 -1.252714 0.191163 0.512178
>>> print(df_obj['a'])
0 1.201658
1 0.128548
2 1.927686
3 -1.281139
4 -0.290666
Name: a, dtype: float64
# 第一个参数索引行,第二个参数是列
>>> print(df_obj.loc[0:2, 'a'])
0 1.201658
1 0.128548
2 1.927686
Name: a, dtype: float64
>>> print(df_obj.loc[1:3,['b','c']])
b c
1 -0.095751 0.415483
2 0.124433 1.118890
3 -0.532217 0.074102
3-2. iloc 位置索引
作用和loc一样,不过是基于索引编号来索引
# Series
>>> print(ser_obj)
a 0
b 1
c 2
d 3
e 4
dtype: int64
>>> print(ser_obj[1:3])
b 1
c 2
dtype: int64
>>> print(ser_obj.iloc[1:3])
b 1
c 2
dtype: int64
# DataFrame
>>> print(df_obj)
a b c d
0 1.201658 0.347192 1.371074 -0.111690
1 0.128548 -0.095751 0.415483 0.152507
2 1.927686 0.124433 1.118890 0.031276
3 -1.281139 -0.532217 0.074102 -0.720960
4 -0.290666 -1.252714 0.191163 0.512178
>>> print(df_obj.iloc[0:2, 0])
0 1.201658
1 0.128548
Name: a, dtype: float64
3-3. ix 标签与位置混合索引
ix是以上二者的综合,既可以使用索引编号,又可以使用自定义索引,要视情况不同来使用
如果索引既有数字又有英文,容易导致定位的混乱,那么这种方式不建议使用的
# Series
>>> print(ser_obj.ix[1:3])
b 1
c 2
dtype: int64
>>> print(ser_obj.ix['b':'c'])
b 1
c 2
dtype: int64
# DataFrame
>>> print(df_obj.loc[0:2, 'a'])
0 1.201658
1 0.128548
2 1.927686
Name: a, dtype: float64
>>> print(df_obj.ix[0:2, 0])
0 1.201658
1 0.128548
2 1.927686
Name: a, dtype: float64
四、Pandas的对齐运算
是数据清洗的重要过程,可以按索引对齐进行运算,如果没对齐的位置则补NaN
Series的对齐运算
1. Series 按行、索引对齐
ser_obj1 + ser_obj2
>>> ser_obj1 = pd.Series(range(10, 20), index = range(10))
>>> ser_obj2 = pd.Series(range(20, 25), index = range(5))
>>> print(ser_obj1)
0 10
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
dtype: int64
>>> print(ser_obj2)
0 20
1 21
2 22
3 23
4 24
dtype: int64
>>> print(ser_obj1.add(ser_obj2))
0 30.0
1 32.0
2 34.0
3 36.0
4 38.0
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
dtype: float64
DataFrame的对齐运算
1. DataFrame 按行、索引对齐
DataFrame做对齐运算时,未对齐数据可以通过fill_value来指定数据做对齐运算
add,sub,mul,div,加减乘除
五、Pandas的函数应用
1. 可直接使用NumPy的函数
在numpy里,可以对数组里的每一个元素进行操作的函数称为ufunc 通用函数(universal function)
在Pandas里可以直接使用Numpy的ufunc
>>> df = pd.DataFrame(np.random.randn(5,4) - 1)
>>> print(df)
0 1 2 3
0 -1.146296 -1.067455 -2.439676 -0.680181
1 -1.835651 -1.495050 -1.646479 -1.546212
2 -0.121636 0.126804 -3.583221 -3.205977
3 -0.361062 0.139010 -0.816511 -0.800901
4 -0.569759 -1.029041 -1.010752 -1.747664
>>> print(np.abs(df))
0 1 2 3
0 1.146296 1.067455 2.439676 0.680181
1 1.835651 1.495050 1.646479 1.546212
2 0.121636 0.126804 3.583221 3.205977
3 0.361062 0.139010 0.816511 0.800901
4 0.569759 1.029041 1.010752 1.747664
2. 通过apply将函数应用到列或行上
Axis参数可以指定轴向,默认值为0,方向是列,值为1:方向是行
>>> f = lambda x : x.max()
>>> print(df.apply(lambda x : x.max()))
0 -0.121636
1 0.139010
2 -0.816511
3 -0.680181
dtype: float64
>>> print(df.apply(lambda x : x.max(), axis=1))
0 -0.680181
1 -1.495050
2 0.126804
3 0.139010
4 -0.569759
dtype: float64
3. 通过applymap将函数应用到每个数据上,只用于DataFrame
>>> f1 = lambda x : '%.2f' % x
>>> print(df.applymap(f1))
0 1 2 3
0 -1.15 -1.07 -2.44 -0.68
1 -1.84 -1.50 -1.65 -1.55
2 -0.12 0.13 -3.58 -3.21
3 -0.36 0.14 -0.82 -0.80
4 -0.57 -1.03 -1.01 -1.75
>>> f2 = lambda x: x+x
>>> print(df_obj.applymap(f2))
a b c d
0 2.403316 0.694383 2.742148 -0.223379
1 0.257097 -0.191501 0.830965 0.305015
2 3.855371 0.248867 2.237779 0.062553
3 -2.562277 -1.064433 0.148205 -1.441920
4 -0.581332 -2.505427 0.382325 1.024356
4.DataFrame对象可以用apply()和applymap()
apply()应用于行,列,可以通过axis来指定
Series对象只能用apply ,效果等于Pyton的map()
ser_obj.map(func)
ser_obj.apply(func)
5.排序
分为按索引排序和按值排序
5-1. 索引排序
sort_index()
排序默认使用升序排序,ascending=False 为降序排序
# Series
>>> ser_obj2 = pd.Series(range(10, 15), index = np.random.randint(5, size=5))
>>> print(ser_obj2)
1 10
1 11
2 12
4 13
4 14
dtype: int64
>>> ser_obj2.sort_index()
1 10
1 11
2 12
4 13
4 14
dtype: int64
>>> print(ser_obj2.sort_index(ascending = False)) #降序排序
4 13
4 14
2 12
1 10
1 11
dtype: int64
5-2.对DataFrame操作时注意轴方向,默认列,axis = 1 为行
# DataFrame
>>> df_obj = pd.DataFrame(np.random.randn(3, 5),
... index=np.random.randint(3, size=3),
... columns=np.random.randint(5, size=5))
>>> print(df_obj )
2 3 3 3 1
2 1.257445 -1.205098 0.128585 0.157959 -0.190920
1 -1.885108 -1.150302 0.688331 0.661057 -0.939931
1 1.220114 -0.820277 -0.691313 -0.562682 1.460008
>>> df_obj_isort = df4.sort_index(axis=1, ascending=False)
>>> print(df_obj_isort)
lval key4 key3
0 4 one foo
1 5 one foo
2 6 one bar
3 7 two bar
5-3.按值排序
sort_values(by='column name')
根据某个唯一的列名进行排序,如果有其他相同列名则报错
①按值排序 - Series对象 – 范例
#创建随机Series对象
>>> ser_obj = pd.Series(np.random.randint(10,20,size= 10))
>>> print(ser_obj)
0 15
1 14
2 12
3 13
4 19
5 10
6 13
7 18
8 11
9 10
dtype: int32
>>> print(ser_obj.sort_values()) #默认升序
5 10
9 10
8 11
2 12
3 13
6 13
1 14
0 15
7 18
4 19
>>> print(ser_obj.sort_values(ascending = False)) #降序
4 19
7 18
0 15
1 14
6 13
3 13
2 12
8 11
9 10
5 10
dtype: int32
②.按值排序 - DataFrame对象 – 范例
如果根据某一个行名/列名来排序时,要保证没有其他相同的行名/列名,axis 指定排序的轴方向
>>> df4 = pd.DataFrame(np.random.randn(3, 5), index=np.random.randint(3, size=3), columns=np.random.randint(5, size=5))
6.处理缺失数据
df_obj = pd.DataFrame([[1,2,np.nan,np.nan], [np.nan,3,4,np.nan],list(range(4)])
# 如果某一列中有一个数是Nan或者浮点数,其他数都转换为浮点数
print(df_obj)
6-1. 判断是否存在缺失值:isnull()
#判断是否NaN值,如果是返回True,否则False
print(df_data.isnull())
6-2. 丢弃缺失数据:dropna()
根据axis轴方向,丢弃包含NaN的行或列。
范例
有NaN的时候把相应的行/列去除掉,默认去除行,axis = 1时,去除列
print(df_obj.dropna())
print(df_obj.dropna(axis = 1))
6-3. 填充缺失数据:fillna()
将NaN值替换为指定的值
范例
将NaN值替换为0
print(df_obj.fillna(0))