Pandas学习笔记
Pandas
链接:https://www.bilibili.com/video/BV1tA411H7cQ?p=1
官方文档:https://pandas.pydata.org/docs/user_guide/index.html#user-guide
简介
numpy能够帮我们处理处理数值型数据,但是我们的数据除了数值之外,还有字符串,还有时间序列等
Pandas的名称来自于面板数据(panel data)
Pandas是一个强大的分析结构化数据的工具集,基于NumPy构建,提供了高级数据结构和数据操作工具,它是使Python成为强大而高效的数据分析环境的重要因素之一。
- 安装
通过pip install pandas
即可安装 - 引入
通过import pandas as pd
引入
Series
Series是一种一维标记的数组行对象,由数据和索引组成,能够保存任何数据类型(int,str,float,object…)。
Series的创建
- 通过list创建
s = pd.Series([1, 2, 3])
print(s)
# 0 1
# 1 2
# 2 3
# dtype: int64
- 通过numpy数组创建
import numpy as np
a=np.arange(0,4)
s = pd.Series(a)
print(s)
# 0 0
# 1 1
# 2 2
# 3 3
# dtype: int32
- 通过字典创建
dict={1:'a',2:'b',3:'c'}
s=pd.Series(dict)
print(s)
# 1 a
# 2 b
# 3 c
# dtype: object
指定索引,用index参数指定:
s = pd.Series(['a','b','c'],index=[1, 2, 3])
print(s)
# 1 a
# 2 b
# 3 c
# dtype: object
用字典创建时,指定的索引没有对应数据会显示NAN。
dic = {'name': 'xx', 'age': 21, 'class': 1}
s = pd.Series(dic, index=['name', 'age', 'class', 'sex'])
print(s)
# name xx
# age 21
# class 1
# sex NaN
# dtype: object
查看索引和数据可分别用s.index
和s.values
。
Series的基本用法
索引操作
- reindex索引重建
s1 = ser_obj.reindex(['b','c','a','f'])
print(s1)
# b 1.0
# c 2.0
# a 0.0
# f NaN
# dtype: float64
- 索引与数据的对应关系不被运算结果影响
s = pd.Series(range(4), index=['a', 'b', 'c', 'd'])
s = s * 2
print(s)
# a 0
# b 2
# c 4
# d 6
# dtype: int64
增删改查
- 增
# 创建
ser_obj=pd.Series(
np.arange(4),
index=['a','b','c','d']
)
# a 0
# b 1
# c 2
# d 3
# dtype: int64
# 对原对象增加
ser_obj['g'] = 9
print(ser_obj)
# a 0
# b 1
# c 2
# d 3
# g 9
# dtype: int64
# 创建新对象
s_add = pd.Series({'f': 7})
s1 = ser_obj.append(s_add)
print(s1)
# a 0
# b 1
# c 2
# d 3
# g 9
# f 7
# dtype: int64
- 删
# 创建
ser_obj=pd.Series(
np.arange(4),
index=['a','b','c','d']
)
# a 0
# b 1
# c 2
# d 3
# dtype: int64
# 在原对象上删
del ser_obj['b']
print(ser_obj)
# a 0
# c 2
# d 3
# dtype: int64
# 创建新对象
s2 = ser_obj.drop('d')
print(s2)
# a 0
# c 2
# dtype: int64
# inplace属性(在原对象上操作)
ser_obj.drop('a',inplace=True)
print(ser_obj)
# c 2
# dtype: int64
- 改
## 创建
ser_obj = pd.Series(np.arange(4), index=['a', 'b', 'c', 'd'])
# a 0
# b 1
# c 2
# d 3
# dtype: int32
# 通过标签索引修改
ser_obj['a'] = 999
print(ser_obj)
# a 999
# b 1
# c 2
# d 3
# dtype: int32
# 通过位置索引修改
ser_obj[0] = 888
print(ser_obj)
# a 888
# b 1
# c 2
# d 3
# dtype: int32
- 查
# 创建
ser_obj = pd.Series(np.arange(4), index=['a', 'b', 'c', 'd'])
# a 0
# b 1
# c 2
# d 3
# dtype: int32
# 行索引
print(ser_obj['a'])# 0
print(ser_obj[1])# 1
# 位置切片索引
print(ser_obj[1: 3])
# b 1
# c 2
# dtype: int32
# 标签切片索引(包含终止索引)
print(ser_obj['b': 'd'])
# b 1
# c 2
# d 3
# dtype: int32
# 不连续索引
print(ser_obj[['a','d']])
# a 0
# d 3
# dtype: int32
print(ser_obj[[0, 3]])
# a 0
# d 3
# dtype: int32
# 布尔索引
print(ser_obj[ser_obj > 1])
# c 2
# d 3
# dtype: int32
- head()与tail()方法
s = pd.Series(range(4), index=['a', 'b', 'c', 'd'])
print(s.head(2)) # 显示前x行
# a 0
# b 1
# dtype: int64
print(s.tail(2)) # 显示后x行
# c 2
# d 3
# dtype: int64
DataFrame
DataFrame 是一个表格型数据结构,它含有一组有序的列,每列可以是不同的数据类型。DataFrame 既有行索引,又有列索引它可以被看做是由Series组成的字典(共用一个索引)。数据是以二维结构存放的。
DataFrame的创建
一、字典类
- 数组、列表或元组构成的字典构造
data = {'a': [1, 2, 3, 4],
'b': (5, 6, 7, 8),
'c': np.arange(9, 13)}
frame = pd.DataFrame(data)
print(frame)
# a b c
# 0 1 5 9
# 1 2 6 10
# 2 3 7 11
# 3 4 8 12
指定索引
data = {'a': [1,2,3,4], 'b': (5,6,7,8), 'c': np.arange(9, 13)}
frame = pd.DataFrame(data,index=[1,2,3,4],columns=['c','b','a','d'])
print(frame)
# c b a d
# 1 9 5 1 NaN
# 2 10 6 2 NaN
# 3 11 7 3 NaN
# 4 12 8 4 NaN
可以使用frame.index
查看行索引,frame.columns
查看列索引,frame.values
查看值(返回一个二维数组)。
- Series构成的字典构造
frame = pd.DataFrame({'a': pd.Series(np.arange(3)),
'b': pd.Series(np.arange(3, 5))})
print(frame)
# a b
# 0 0 3.0
# 1 1 4.0
# 2 2 NaN
- 字典构成的字典构造
data={
'a':{'A':1,'B':2},
'b':{'A':3,'B':4},
'c':{'A':5}
}
frame=pd.DataFrame(data)
print(frame)
# a b c
# A 1 3 5.0
# B 2 4 NaN
二、列表类
- 二维数组构造
data = np.arange(12).reshape(4,3)
frame = pd.DataFrame(data,columns=['a','b','c'])
print(frame)
# a b c
# 0 0 1 2
# 1 3 4 5
# 2 6 7 8
# 3 9 10 11
- 字典构成的列表构造
data = [{'A':1,'B':2},{'A':3,'B':4},{'A':5}]
frame=pd.DataFrame(data)
print(frame)
# A B
# 0 1 2.0
# 1 3 4.0
# 2 5 NaN
- Series构成的列表构造
data = [
pd.Series(np.arange(3)),
pd.Series(np.arange(2))
]
frame=pd.DataFrame(data)
print(frame)
# 0 1 2
# 0 0.0 1.0 2.0
# 1 0.0 1.0 NaN
DataFrame的基本用法
索引操作
- 通过列索引获取列数据(Series类型)
print(frame['A'])
# a 0
# b 3
# c 6
# Name: A, dtype: int32
- 索引重建
# 1.行索引重建
df1 = df_obj.reindex(['a', 'b', 'c', 'd'])
print(df1)
# A B C
# a 0.0 1.0 2.0
# b 3.0 4.0 5.0
# c 6.0 7.0 8.0
# d NaN NaN NaN
# 2.列索引重建
df2 = df_obj.reindex(columns=['C', 'B', 'A', 'D'])
print(df2)
# C B A D
# a 2 1 0 NaN
# b 5 4 3 NaN
# c 8 7 6 NaN
增删改查
- 增
# 创建
df_obj=pd.DataFrame(
np.arange(9).reshape(3,3),
index=['a','b','c'],
columns=['A','B','C']
)
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
# 末尾增加列
df_obj[4] = [10, 11, 12]
print(df_obj)
# A B C 4
# a 0 1 2 10
# b 3 4 5 11
# c 6 7 8 12
# 插入增加列
df_obj.insert(0, 'E', [100, 101, 102])
print(df_obj)
# E A B C 4
# a 100 0 1 2 10
# b 101 3 4 5 11
# c 102 6 7 8 12
# 增加行
df_obj.loc['d'] = [1, 1, 1, 1, 1]
print(df_obj)
# E A B C 4
# a 100 0 1 2 10
# b 101 3 4 5 11
# c 102 6 7 8 12
# d 1 1 1 1 1
# 创建新对象
row = {'E': 5, 'A': 4, 'B': 3, 'C': 2, 4: 1}
df1 = df_obj.append(row, ignore_index=True)
print(df1) # 会忽略行索引
# E A B C 4
# 0 100 0 1 2 10
# 1 101 3 4 5 11
# 2 102 6 7 8 12
# 3 1 1 1 1 1
# 4 5 4 3 2 1
- 删
# 创建
df_obj=pd.DataFrame(
np.arange(9).reshape(3,3),
index=['a','b','c'],
columns=['A','B','C']
)
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
# 删除列
del df_obj['C']
print(df_obj)
# A B
# a 0 1
# b 3 4
# c 6 7
# 创建新对象
# 删除行
df2 = df_obj.drop(['a', 'b'])
print(df2)
# A B
# c 6 7
# 删除列
df3 = df_obj.drop('A',axis=1)# 或axis='columns'
print(df3)
# B
# a 1
# b 4
# c 7
# inplace属性(在原对象上操作)
df_obj.drop('a',inplace=True)
print(df_obj)
# A B
# b 3 4
# c 6 7
- 改
## 重新创建
df_obj = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
## 修改列
# 通过列索引修改
df_obj['A']=[10,11,12]
print(df_obj)
# A B C
# a 10 1 2
# b 11 4 5
# c 12 7 8
## 修改行
# loc高级索引
df_obj.loc['a']=7
print(df_obj)
# A B C
# a 7 7 7
# b 11 4 5
# c 12 7 8
## 修改单个数据
df_obj.loc['a','A']=100
print(df_obj)
# A B C
# a 100 7 7
# b 11 4 5
# c 12 7 8
- 查
# 创建
df_obj = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
# 列索引
print(df_obj['A'])
# a 0
# b 3
# c 6
# Name: A, dtype: int32
# 取多列
print(df_obj[['A','C']])
# a 0
# b 3
# c 6
# Name: A, dtype: int32
# 选取一个值
print(df_obj['A']['a'])
# 0
# 切片
print(df_obj[1:3])# 获取行
# A B C
# b 3 4 5
# c 6 7 8
常用函数
- T转置
frame=pd.DataFrame(
np.arange(9).reshape(3,3),
index=['a','b','c'],
columns=['A','B','C']
)
print(frame)
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
print(frame.T)
# a b c
# A 0 3 6
# B 1 4 7
# C 2 5 8
高级索引
loc标签索引
loc是基于标签名的索引
ser_obj = pd.Series(np.arange(4), index=['a', 'b', 'c', 'd'])
# a 0
# b 1
# c 2
# d 3
# dtype: int32
print(ser_obj.loc['a':'c'])
# a 0
# b 1
# c 2
# dtype: int32
df_obj = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
print(df_obj.loc['a':'b','A':'B'])
# A B
# a 0 1
# b 3 4
iloc位置索引
iloc是基于位置的索引
print(ser_obj.iloc[1: 3])
# b 1
# c 2
# dtype: int32
print(df_obj.iloc[0: 2, 0: 2])
# A B
# a 0 1
# b 3 4
Pandas对齐运算
是数据清洗的重要过程,可以按索引对齐进行运算,如果没对齐的位置则补NaN,最后也可以填充NaN。
Series的对齐运算
s1 = pd.Series(range(10, 18), index=range(8))
s2 = pd.Series(range(0, 5), index=range(5))
print(s1)
# 0 10
# 1 11
# 2 12
# 3 13
# 4 14
# 5 15
# 6 16
# 7 17
# dtype: int64
print(s2)
# 0 0
# 1 1
# 2 2
# 3 3
# 4 4
# dtype: int64
print(s1 + s2)
# 0 10.0
# 1 12.0
# 2 14.0
# 3 16.0
# 4 18.0
# 5 NaN
# 6 NaN
# 7 NaN
# dtype: float64
DataFrame的对齐运算
df1 = pd.DataFrame(np.ones((2, 2)), columns=['a', 'b'])
df2 = pd.DataFrame(np.ones((3, 3)), columns=['a', 'b', 'c'])
print(df1)
# a b
# 0 1.0 1.0
# 1 1.0 1.0
print(df2)
# a b c
# 0 1.0 1.0 1.0
# 1 1.0 1.0 1.0
# 2 1.0 1.0 1.0
print(df1 + df2)
# a b c
# 0 2.0 2.0 NaN
# 1 2.0 2.0 NaN
# 2 NaN NaN NaN
填充未对齐的数据进行运算
通过fill_value指定填充值,未对齐的数据将和填充值做运算
print(df1.add(df2, fill_value=0))
# a b c
# 0 2.0 2.0 1.0
# 1 2.0 2.0 1.0
# 2 1.0 1.0 1.0
算术方法表:
方法 | 描述 |
---|---|
add,radd | 加法(+) |
sub,rsub | 减法(-) |
div,rdiv | 除法(/) |
floordiv,rfllordiv | 整除(//) |
mul,rmul | 乘法(*) |
pow,rpow | 幂次方(**) |
r表示反转,如df.rdiv(1)等价于1/df。
Pandas和Series的混合运算
df = pd.DataFrame(np.arange(0, 9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
print(df)
# A B C
# a 0 1 2
# b 3 4 5
# c 6 7 8
# 沿行广播
s1 = df.iloc[0]
df1 = df - s1
print(df1)
# A B C
# a 0 0 0
# b 3 3 3
# c 6 6 6
# 沿列广播
s2 = df['A']
df2 = df.sub(s2, axis=0)# 或axis='index'
print(df2)
# A B C
# a 0 1 2
# b 0 1 2
# c 0 1 2
Pandas函数应用
apply和applymap
- 可直接用numpy函数
df = pd.DataFrame(np.random.randn(3,3)-1)
print(df)
# 0 1 2
# 0 -1.343551 -1.076263 -1.581763
# 1 -1.709353 -0.440628 -0.932154
# 2 -0.404007 1.355786 -2.136552
print(np.abs(df))
# 0 1 2
# 0 1.343551 1.076263 1.581763
# 1 1.709353 0.440628 0.932154
# 2 0.404007 1.355786 2.136552
- 通过apply将函数应用到列或行上
df = pd.DataFrame(np.random.randint(0,10,size=(3,3)))
print(df)
# 0 1 2
# 0 3 0 0
# 1 9 7 4
# 2 0 4 5
f=lambda x: x.max()
# 轴的方向,默认axis=0,方向是列
print(df.apply(f))
# 0 9
# 1 7
# 2 5
# dtype: int64
# 指定轴方向,axis=1,方向是行
print(df.apply(f,axis=1))
# 0 3
# 1 9
# 2 5
# dtype: int64
- 通过applymap将函数应用到每个数据上
df = pd.DataFrame(np.random.randn(3,3))
print(df)
# 0 1 2
# 0 -1.210624 0.274528 0.451047
# 1 0.918385 0.518988 0.753193
# 2 0.157231 -1.159313 2.241481
f = lambda x : '%.2f' % x # 保留两位小数
print(df.applymap(f))
# 0 1 2
# 0 -1.21 0.27 0.45
# 1 0.92 0.52 0.75
# 2 0.16 -1.16 2.24
排序
- 索引排序
sort_index()
排序默认使用升序排序,ascending=False 为降序排序
s = pd.Series(range(10, 15), index=np.random.randint(5, size=5))
print(s)
# 0 10
# 2 11
# 3 12
# 4 13
# 1 14
# dtype: int64
s.sort_index(ascending=False, inplace=True)
print(s)
# 4 13
# 3 12
# 2 11
# 1 14
# 0 10
# dtype: int64
对DataFrame操作时注意轴方向
df = pd.DataFrame(np.random.randint(0, 10, size=(3, 5)),
index=np.random.randint(3, size=3),
columns=np.random.randint(5, size=5))
print(df)
# 0 2 0 3 2
# 2 1 1 5 2 5
# 2 2 8 7 0 3
# 0 7 1 6 7 4
df.sort_index(axis=1, inplace=True)
print(df)
# 0 0 2 2 3
# 2 1 5 1 5 2
# 2 2 7 8 3 0
# 0 7 6 1 4 7
- 按值排序
sort_values(by=‘column name’)
根据某个唯一的列名进行排序,如果有其他相同列名则报错。
df = pd.DataFrame(np.random.randint(10, size=(4,3)),
index=np.random.randint(10, size=4),
columns=['A','B','C'])
print(df)
# A B C
# 3 9 4 6
# 2 5 0 4
# 4 7 4 6
# 7 3 2 8
df.sort_values(by='A', inplace=True)
print(df)
# A B C
# 7 3 2 8
# 2 5 0 4
# 4 7 4 6
# 3 9 4 6
处理缺失值
- 判断是否存在缺失值:isnull()
df = pd.DataFrame({'a':{'A':1,'B':2},'b':{'B':4},'c':{'A':5}})
print(df)
# a b c
# A 1 NaN 5.0
# B 2 4.0 NaN
print(df.isnull())
# a b c
# A False True False
# B False False True
print(df.notnull())
# a b c
# A True False True
# B True True False
- 丢弃缺失数据:dropna()
根据axis轴方向,丢弃包含NaN的行或列。
df = pd.DataFrame({'a':{'A':1,'B':2},'b':{'A':3,'B':4},'c':{'A':5}})
print(df)
# a b c
# A 1 3 5.0
# B 2 4 NaN
print(df.dropna())
# a b c
# A 1 3 5.0
print(df.dropna(axis=1))
# a b
# A 1 3
# B 2 4
- 填充缺失数据:fillna()
df = pd.DataFrame({'a':{'A':1,'B':2},'b':{'B':4},'c':{'A':5}})
print(df)
# a b c
# A 1 NaN 5.0
# B 2 4.0 NaN
print(df.fillna(100))
# a b c
# A 1 100.0 5.0
# B 2 4.0 100.0
Pandas层级索引
下面创建一个Series, 在输入索引Index时,输入了由两个子list组成的list,第一个子list是外层索引,第二个list是内层索引。
ser_obj = pd.Series(np.arange(12),index=[
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd'],
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
])
print(ser_obj)
# a 0 0
# 1 1
# 2 2
# b 0 3
# 1 4
# 2 5
# c 0 6
# 1 7
# 2 8
# d 0 9
# 1 10
# 2 11
# dtype: int32
- MultiIndex索引对象
打印这个Series的索引类型,显示是MultiIndex
print(type(ser_obj.index))
# <class 'pandas.core.indexes.multi.MultiIndex'>
选取子集
- 外层选取:
根据索引获取数据。当通过外层索引获取数据的时候,可以直接利用外层索引的标签来获取。
print(ser_obj['c'])
# 0 6
# 1 7
# 2 8
# dtype: int32
- 内层选取
当要通过内层索引获取数据的时候,在list中传入两个元素,前者是表示要选取的外层索引,后者表示要选取的内层索引。
print(ser_obj[:, 2])
# a 2
# b 5
# c 8
# d 11
# dtype: int32
常用于分组操作、透视表的生成等
交换分层顺序
.swaplevel( )交换内层与外层索引。
print(ser_obj.swaplevel())
# 0 a 0
# 1 a 1
# 2 a 2
# 0 b 3
# 1 b 4
# 2 b 5
# 0 c 6
# 1 c 7
# 2 c 8
# 0 d 9
# 1 d 10
# 2 d 11
# dtype: int32
Pandas统计计算和描述
保留小数位
df1 = pd.DataFrame(np.random.rand(4,3),columns=list('ABC'),index=list('abcd'))
f = lambda x: '%.2f'% x
df2 = df1.applymap(f).astype(float)
print(df2)
# A B C
# a 0.26 1.00 0.50
# b 0.34 0.18 0.09
# c 0.16 0.45 0.01
# d 0.07 0.01 0.51
常用的统计计算
sum, mean, max, min…
- axis=0 按列统计,axis=1按行统计
- skipna 排除缺失值, 默认为True
print(df2.sum())
#默认把这一列的Series计算,所有行求和
# A 0.83
# B 1.64
# C 1.11
# dtype: float64
print(df2.sum(axis='columns'))
#指定求每一行的所有列的和
# a 1.76
# b 0.61
# c 0.62
# d 0.59
# dtype: float64
print(df2.idxmax())
#查看每一列所有行的最大值所在的标签索引,也可以通过axis='columns'求每一行所有列的最大值的标签索引
# A b
# B a
# C d
# dtype: object
常用的统计描述
describe 产生多个统计数据
print(df2.describe())#查看汇总
# A B C
# count 4.000000 4.000000 4.000000
# mean 0.430000 0.512500 0.465000
# std 0.224796 0.362985 0.490748
# min 0.200000 0.170000 0.010000
# 25% 0.290000 0.245000 0.062500
# 50% 0.400000 0.460000 0.440000
# 75% 0.540000 0.727500 0.842500
# max 0.720000 0.960000 0.970000
pct_change查看当前元素与先前元素的相差百分比
print(df2.pct_change())# 同样指定axis='columns'列与列的百分比变化
# A B C
# a NaN NaN NaN
# b -0.146667 -0.410714 -0.041096
# c -0.968750 0.939394 0.385714
# d 14.000000 -0.593750 -0.783505
常用的统计描述方法
方法 | 说明 |
---|---|
count | 非NAN值得数量 |
describe | 针对Series或DataFrame列计算汇总统计 |
min,max | 计算最小值与最大值 |
argmin,argmax | 计算最小值和最大值的索引位置 |
idxmin,idxmax | 计算最小值和最大值的标签索引 |
quantile | 计算样本的分位数(0到1) |
sum | 值的总和 |
mean | 值的平均数 |
median | 值的算数中位数(50%分位数) |
mad | 根据平均值计算平均绝对离差 |
var | 样本值的方差 |
std | 样本值的标准差 |
skew | 样本值的偏度(三阶矩) |
kurt | 样本值的峰度(四阶矩) |
cumsum | 样本值的累计和 |
cummin,cummax | 样本值的累积最大值和累积最小值 |
cumprod | 样本值的累计积 |
diff | 计算一阶差分(使用时间序列) |
pct_change | 计算百分比变化 |
Axis的理解
通俗的讲,axis = 0就是作用在行标签上,axis = 1就是作用在列标签上
如:
df.drop(index,axis=0)是去掉某一行数据;
df.sum(axis=0)是对行标签对应的数进行求和,即每列所有行求和。
【注】:部分资源来源于网络,若侵犯了您的权利,请与作者联系,感谢!