Pandas基本操作(简单series和dataframe)
本文章说明介绍series和dataframe两种数据类型基本的简单操作,后续更新多重操作
一、什么是pandas
1. 简介
1)Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的;
2)pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具;
3)pandas提供了大量能使我们快速便捷地处理数据的函数和方法;
4)它是使Python成为强大而高效的数据分析环境的重要因素之一。
2. 数据结构
Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近。Series如今能保存不同种数据类型,字符串、boolean值、数字等都能保存在Series中。
Time- Series:以时间为索引的Series。
DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。
Panel :三维的数组,可以理解为DataFrame的容器。
二、Series
1. 什么是Series
Series是一种类似于一维数组的对象,能够保存任何数据类型(整数,字符串,浮点数,Python对象等),由下面两个部分组成:
values:一组数据(ndarray类型)
index:相关的数据索引标签
Series(
data=None,
index=None,
dtype=None,
name=None,
copy=False,
fastpath=False,
)
参数说明:
data:数据,可以是数组、可迭代对象、字典或者包含顺序存储的数据;当为字典时,如果不再指定index,则key为index,value为data
index:与data具有相同长度的索引值;不唯一;如果不提供,默认为RangeIndex (0, 1, 2, ..., n);如果同时使用index和字典,将会覆盖字典的keys
dtype:输出的元素类型,如果不指定,与的data一致
name:给输出的Series指定一个name名称属性
2. Series的创建
from pandas import Series
2.1 由列表或numpy数组创建
1.特别地,由ndarray创建的是引用,而不是副本。对Series元素的改变也会改变原来的ndarray对象中的元素。(列表没有这种情况)
2.由列表创建series,创建的是副本(深拷贝)
# 由列表创建series
l = [1,2,3,4,5]
s = Series(l)
s[0] = 20
s
>>0 20
1 2
2 3
3 4
4 5
dtype: int64
# 由numpy创建
n = np.array([1,2,3,4,5])
s = Series(n, )
s.index=list('ABCDE')#还可以通过设置index参数指定索引
s
>>A 1
B 2
C 3
D 4
E 5
dtype: int32
2.2 由字典创建
data_dict = {'A': 1, 'B': 2, 'C': 3, 'D':4}
s = Series(data_dict)
s
>>A 1
B 2
C 3
D 4
dtype: int64
3. Series的索引和切片
可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分为显示索引和隐式索引:
3.1 显式索引
#Series操作实例
data = np.random.randint(0,10, size=10)
index = list('abcdefghij')
s = Series(data=data, index=index)
s
>>a 6
b 6
c 7
d 4
e 6
f 3
g 8
h 1
i 6
j 6
dtype: int32
- 使用index中的元素作为索引值
- 使用.loc[](推荐)
#第一种,直接写中括号
s['d']
>>4
# 第二种,使用loc[], location 推荐写法.
s.loc['d']
>>4
3.2 隐式索引
- 使用整数作为索引值
- 使用.iloc[](推荐)
s.iloc[3]
>>4
s[3]
>>4
3.3 对比总结
s.index = np.arange(0,10)#修改s的索引
s
>>0 6
1 6
2 7
3 4
4 6
5 3
6 8
7 1
8 6
9 6
dtype: int32
在这种情况下,使用s[]没有办法再去区分显式索引隐式索引
故:1)在Series中,永远不要使用直接中括号进行索引.
2)推荐显式索引用.loc[], 隐式索引用.iloc[]
3.4 切片
在3.3的基础上
#显式切片,全闭区间,左右都可以取到
s.loc[1:5]
>>1 6
2 7
3 4
4 6
5 3
dtype: int32
# 隐式索引的切片 左闭右开.
s.iloc[1:5]
>>1 6
2 7
3 4
4 6
dtype: int32
3.5 练习
============================================
练习2:
使用多种方法对练习1创建的Series s1进行索引和切片:
找到数学对应的成绩
索引: 数学 150
切片: 语文 150 数学 150 英语 150
============================================
data = [150,150,150, 300]
index = ['语文', '数学', '英语', '理综']
s1 = Series(data=data, index=index)
s1
>>语文 150
数学 150
英语 150
理综 300
dtype: int64
#找到数学对应的成绩(获取的是一个值)
#显式
s1.loc['数学']
#隐式
s1.iloc[1]
>>150
#索引: 数学 150(获取的是Series)
# 索引的时候,再套一层总括还,那么还会返回原来数据类型
#显式
s1.loc[['数学']]
#隐式
s1.iloc[[1]]
>>数学 150
dtype: int64
#切片: 语文 150 数学 150 英语 150
#显式
s1.loc['语文':'英语']
#隐式
s1.iloc[:3]
>>语文 150
数学 150
英语 150
dtype: int64
4. Series的属性
可以把Series看成一个定长的有序字典
4.1 属性
可以通过shape,size,index,values等得到series的属性
Series对象本身及其实例都有一个name属性
以3.5中的s1为例
s1.shape#元组形式返回基础数据的形状
>>(4,)
s1.size#返回基础数据的数量
>>4
s1.index
>>Index(['语文', '数学', '英语', '理综'], dtype='object')
s1.values
>>array([150, 150, 150, 300], dtype=int64)
s = Series({'a': np.nan, 'b': 1, 'c': 2, 'd': 3}, name='test')
s
>>a NaN
b 1.0
c 2.0
d 3.0
Name: test, dtype: float64
4.2 样式快速查看
可以通过head(),tail()快速查看Series对象的样式(DataFrme中也有)
#head():默认返回前5个,也可给定具体的数目
s.head(2)
>>1 9
2 9
dtype: int32
tile():默认返回后5个,也可给定具体的数目
4.3 缺失数据显示NaN(not a number)
当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
s = Series({'a': np.nan, 'b': 1, 'c': 2, 'd': 3})
s
>>a NaN
b 1.0
c 2.0
d 3.0
dtype: float64
可以使用pd.isnull(),pd.notnull(),或自带isnull(),notnull()函数检测缺失数据
pd.isnull(s)
>>a True
b False
c False
d False
dtype: bool
pd.notnull(s)
>>a False
b True
c True
d True
dtype: bool
s.isnull()
>>a True
b False
c False
d False
dtype: bool
s.notnull()
>>a False
b True
c True
d True
dtype: bool
5. Series的计算
5.1 与数进行运算
适用于numpy的数组运算也适用于Series
s + 1
a NaN #与数进行运算为NaN
b 2.0
c 3.0
d 4.0
dtype: float64
data = [150,150,150, 300]
index = ['语文', '数学', '英语', '理综']
s1 = Series(data=data, index=index)
s1
>>语文 150
数学 150
英语 150
理综 300
dtype: int64
s1 + 1 # Series和单个数字运算,每个元素分别和这个数字运算.
>>语文 151
数学 151
英语 151
理综 301
Name: Series, dtype: int64
5.2 Series之间进行运算
在运算中自动对齐不同索引的数据
如果索引不对应,则补NaN
Series和Series之间的运算根据索引进行运算,相同的索引才会进行运算,索引不同,补NaN.
要想保留所有的value,则需要使用.add()函数,s.add(ss, fill_value=0),使得fill_value=0
#索引相同,对应的位置数据进行运算(+-*/一样)
s = Series({'a':1, 'b':2, 'c': 3})
ss = Series({'a':1, 'b':2, 'c': 3})
display(s,ss)
>>a 1
b 2
c 3
dtype: int64
a 1
b 2
c 3
dtype: int64
s + ss
>>a 2
b 4
c 6
dtype: int64
#索引不同,补NaN,相同的索引计算同上(+-*/一样)
s = Series({'a':1, 'b':2, 'c': 3})
ss = Series({ 'b':2, 'c': 3, 'd':4})
display(s,ss)
>>a 1
b 2
c 3
dtype: int64
b 2
c 3
d 4
dtype: int64
s + ss
>>a NaN
b 4.0
c 6.0
d NaN
dtype: float64
s / ss
>>a NaN
b 1.0
c 1.0
d NaN
dtype: float64
5.2 练习
============================================
练习3:
想一想Series运算和ndarray运算的规则有什么不同?
新建另一个索引包含“文综”的Series s2,并与s1进行多种算术操作。思考如何保存所有数据。
============================================
1)ndarray有广播机制,Series没有广播机制;
2)Series根据相同的索引进行运算,索引不同补NaN,ndarry进行广播,广播失败则报错
data = [150,150,150, 300]
index = ['语文', '数学', '英语', '理综']
s1 = Series(data=data, index=index)
s1
>>语文 150
数学 150
英语 150
理综 300
dtype: int64
s2 = Series({'语文': 150, '数学': 150, '英语': 150, '文综': 300})
s2
>>语文 150
数学 150
英语 150
文综 300
dtype: int64
s1+s2
数学 300.0
文综 NaN
理综 NaN
英语 300.0
语文 300.0
dtype: float64
s1.add(s2, fill_value=0)#索引不同,不存在的一方默认该值为0
数学 300.0
文综 300.0
理综 300.0
英语 300.0
语文 300.0
dtype: float64
三、DataFrame
1. 什么是DateFrame
DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
- 行索引:index
- 列索引:columns
- 值:values(numpy的二维数组)
DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
data:可以是ndarray、可迭代对象、字典等
index:生成索引(行),不指定默认为RangeIndex
columns:生成列标签,不指定默认为RangeIndex
dtype:要强制执行的数据类型。只允许一个dtype。如果没有,推断出
2. DataFrame的创建
2.1 给定参数来创建
# 推荐写法
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语', 'python']
data = np.random.randint(0,150, size=(4,4,))
df = DataFrame(data=data, index=index, columns=columns)
df
>>
语文 数学 英语 python
张三 102 149 127 148
李四 40 84 16 39
王五 82 124 28 17
赵六 46 137 148 96
2.2 字典创建
# 字典创建DataFrame, 字典的key是列索引
df = DataFrame({'语文': np.random.randint(0,150, size=4), '数学': np.random.randint(0,150, size=4), '英语': np.random.randint(0,150, size=4), 'python': np.random.randint(0,150, size=4)}, index = ['张三', '李四', '王五', '赵六'])
# df.index = ['张三', '李四', '王五', '赵六']
df
>>
语文 数学 英语 python
张三 146 24 107 70
李四 135 26 54 38
王五 113 135 103 117
赵六 30 3 23 102
dict = {'张三':[150,150,150,300],'李四':[0,0,0,0]}
index = ['语文', '数学', '英语', '理综']
df = DataFrame(dict, index=index)
df
>>
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 300 0
2.3 练习
============================================
练习4:
根据以下考试成绩表,创建一个DataFrame,命名为df:
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 300 0
============================================
#方法1
dict = {'张三':[150,150,150,300],'李四':[0,0,0,0]}
index = ['语文', '数学', '英语', '理综']
df = DataFrame(dict, index=index)
df
>>
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 300 0
#方法2
data = [[150, 0], [150, 0], [150, 0], [300, 0]]
index = ['语文', '数学', '英语', '理综']
columns = ['张三', '李四']
df = DataFrame(data=data, index=index, columns=columns)
df
3.DataFrame的属性
3.1 values、columns、index、shape
DataFrame属性:values、columns、index、shape
以2.2df为例:
df.values
>>array([[146, 24, 107, 70],
[135, 26, 54, 38],
[113, 135, 103, 117],
[ 30, 3, 23, 102]])
df.shape
>>(4, 4)
# 行索引
df.index
>>Index(['张三', '李四', '王五', '赵六'], dtype='object')
# 列索引
df.columns
>>Index(['语文', '数学', '英语', 'python'], dtype='object')
4. DataFrame的索引和切片
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语', 'python']
data = np.random.randint(0,150, size=(4,4,))
df = DataFrame(data=data, index=index, columns=columns)
df
>>
语文 数学 英语 python
张三 121 143 60 33
李四 103 19 111 36
王五 117 33 109 38
赵六 1 106 40 122
4.1 对列进行操作
# 对列进行索引 ,推荐使用直接中括号.
- 通过类似字典的方式
df['语文']#推荐
- 通过属性的方式
df.语文
#结果一致
>>张三 121
李四 103
王五 117
赵六 1
Name: 语文, dtype: int32
可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
#返回DataFrame
df[['语文']]
>>
语文
张三 121
李四 103
王五 117
赵六 1
#索引获取DataFrame多行方法
df[['语文','数学']]
>>
语文 数学
张三 121 143
李四 103 19
王五 117 33
赵六 1 106
#新增一列
df['理综'] = np.random.randint(0,300, size=4)
df
>>
语文 数学 英语 python 理综
张三 121 143 60 33 160
李四 103 19 111 36 195
王五 117 33 109 38 86
赵六 1 106 40 122 265
#对列显式切片
df.loc[:, '数学': 'python']
>>
数学 英语 python
张三 143 60 33
李四 19 111 36
王五 33 109 38
赵六 106 40 122
#对列隐式切片
df.iloc[:, 1:3]
数学 英语
张三 143 60
李四 19 111
王五 33 109
赵六 106 40
4.2 对行进行操作
#索引
- 使用.loc[]加index来进行行索引
# 显式
df.loc[['张三', '李四']]#可以索引多个
>>
语文 数学 英语 python 理综
张三 121 143 60 33 160
李四 103 19 111 36 195
df.loc['张三']
语文 121
数学 143
英语 60
python 33
理综 160
Name: 张三, dtype: int32
- 使用.iloc[]加整数来进行行索引
df.iloc[[1]]
>>
语文 数学 英语 python
李四 103 19 111 36
同样返回一个Series,index为原来的columns。
# 新增一行
df.loc['田七'] = np.random.randint(0,150, size=5)
df
>>
语文 数学 英语 python 理综
张三 121 143 60 33 160
李四 103 19 111 36 195
王五 117 33 109 38 86
赵六 1 106 40 122 265
田七 53 115 8 128 100
#行切片
# 操作行的时候,显式使用.loc
df.loc['张三': '王五']
>>
语文 数学 英语 python 理综
张三 121 143 60 33 160
李四 103 19 111 36 195
王五 117 33 109 38 86
# 使用隐式索引进行切片.
df.iloc[1:3]
>>
语文 数学 英语 python 理综
李四 103 19 111 36 195
王五 117 33 109 38 86
4.3 对元素操作
- 使用列索引
- 使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
- 使用values属性(二维numpy数组)
# 先行后列,相当于一致对行进行操作
df.loc['王五'].loc['英语']
# 优化写法,也是推荐写法
df.loc['王五', '英语']
>>109
# 先列后行,相当于一致对列进行操作
df['英语']['王五']
>>109
#不可简化成df['英语', '王五']
#2, 找张三的语文成绩,要求返回的是一个DataFrame
df.loc[['张三'], ['语文']]
4.4 对比总结
【注意】 直接用中括号时:
- 索引表示的是列索引
- 切片表示的是行切片
总结:
1, 行索引永远用.loc[]
2, 列索引永远用[]
3, 索引元素的时候,先找行再找列,使用.loc[index, column]
4, 切片的时候,直接使用中括号是对行切片 , 对列进行切片也需要先从行开始 .loc[:, column: column]
5,获得DataFrame格式添加[]
4.5 设置索引set_index
#设置索引set_index
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语', 'python']
data = np.random.randint(0,150, size=(4,4,))
df = DataFrame(data=data, index=index, columns=columns)
df
>>
语文 数学 英语 python
张三 57 118 95 78
李四 34 2 35 98
王五 18 73 24 137
赵六 84 80 128 74
df.set_index('语文')
>>
数学 英语 python
语文
57 118 95 78
34 2 35 98
18 73 24 137
84 80 128 74
4.6 练习
1, 找张三的语文成绩
2, 找张三的语文成绩,要求返回的是一个DataFrame
3, 切语文到英语
4, 切李四到赵六
df
>>
语文 数学 英语 python 理综
张三 121 143 60 33 160
李四 103 19 111 36 195
王五 117 33 109 38 86
赵六 1 106 40 122 265
田七 53 115 8 128 100
#1, 找张三的语文成绩
#先行后列(推荐简化版)
df.loc['张三'].loc['语文']
df.loc['张三','语文']
#先列后行
df['语文']['张三']
>>121
#2, 找张三的语文成绩,要求返回的是一个DataFrame
df.loc[['张三'], ['语文']]
#3, 切语文到英语
df.loc[:,'语文':'英语']
#4, 切李四到赵六
df.loc['李四':'赵六']
5. DataFrame的运算
5.1 DataFrame和单个数字的运算
各元素都进行运算
df + 1
>>
语文 数学 英语 python 理综
张三 122 144 61 34 161
李四 104 20 112 37 196
王五 118 34 110 39 87
赵六 2 107 41 123 266
田七 54 116 9 129 101
5.2 DataFrame之间的运算
同Series一样:
- 在运算中自动对齐不同索引的数据
- 如果索引不对应,则补NaN
#索引一致,对应位置元素进行运算
#DataFrame和DateFrame之间进行运算的时候,行列索引都一致的元素才能进行运算,否则补NaN
df2 = df.copy()
df2
>>
语文 数学 英语 python 理综
张三 122 144 61 34 161
李四 104 20 112 37 196
王五 118 34 110 39 87
赵六 2 107 41 123 266
田七 54 116 9 129 101
df + df2
>>
语文 数学 英语 python 理综
张三 242 286 120 66 320
李四 206 38 222 72 390
王五 234 66 218 76 172
赵六 2 212 80 244 530
田七 106 230 16 256 200
##DataFrame和DateFrame之间进行运算的时候,行列索引都一致的元素才能进行运算,否则补NaN
df2.columns = ['语文', '数学', '英语', 'python', '文综']
df2
>>
语文 数学 英语 python 文综
张三 121 143 60 33 160
李四 103 19 111 36 195
王五 117 33 109 38 86
赵六 1 106 40 122 265
田七 53 115 8 128 100
df + df2
>>
python 数学 文综 理综 英语 语文
张三 66 286 NaN NaN 120 242
李四 72 38 NaN NaN 222 206
王五 76 66 NaN NaN 218 234
赵六 244 212 NaN NaN 80 2
田七 256 230 NaN NaN 16 106
#增加填充,保留数据
df.add(df2, fill_value=0)
>>
python 数学 文综 理综 英语 语文
张三 66 286 160.0 160.0 120 242
李四 72 38 195.0 195.0 222 206
王五 76 66 86.0 86.0 218 234
赵六 244 212 265.0 265.0 80 2
田七 256 230 100.0 100.0 16 106
5.3 Series与DataFrame之间的运算
【重要】
-
使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)
-
使用pandas操作函数:
axis=0:以列为单位操作(参数必须是列),对所有列都有效。 axis=1:以行为单位操作(参数必须是行),对所有行都有效。
df#操作原型
>>
语文 数学 英语 python 理综
张三 121 143 60 33 160
李四 103 19 111 36 195
王五 117 33 109 38 86
赵六 1 106 40 122 265
田七 53 115 8 128 100
s = Series(index=['语文', '数学', '英语', 'python', '理综'], data=np.random.randint(0,150, size=(5)))
s#创建一个series
>>语文 145
数学 117
英语 6
python 132
理综 113
dtype: int32
df + s#列索引一致时相加,相当于df中每一行都去与s进行对应相加
>>
语文 数学 英语 python 理综
张三 266 260 66 165 273
李四 248 136 117 168 308
王五 262 150 115 170 199
赵六 146 223 46 254 378
田七 198 232 14 260 213
s = Series(index=['张三', '李四', '王五', '赵六', '田七'], data=np.random.randint(0,150, size=(5)))
s
>>张三 3
李四 123
王五 103
赵六 22
田七 28
dtype: int32
s + df # 列索引一致才进行运算,列索引不一致补NaN.
>>
python 张三 数学 李四 王五 理综 田七 英语 语文 赵六
张三 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
李四 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
王五 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
赵六 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
田七 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
df.add(s, axis='index')
语文 数学 英语 python 理综
张三 124 146 63 36 163
李四 226 142 234 159 318
王五 220 136 212 141 189
赵六 23 128 62 144 287
田七 81 143 36 156 128
总结:
- DataFrame和Series进行运算的时候,默认是按照DataFrame的列索引进行操作, 列索引一致才进行运算,列索引不一致补NaN.
2)可以通过pandas封装的运算函数的axis来修改操作的方向.
5.4 练习
============================================
练习6:
假设ddd是期中考试成绩,ddd2是期末考试成绩,请自由创建ddd2,并将其与ddd相加,求期中期末平均值。
假设张三期中考试数学被发现作弊,要记为0分,如何实现?
李四因为举报张三作弊立功,期中考试所有科目加100分,如何实现?
后来老师发现有一道题出错了,为了安抚学生情绪,给每位学生每个科目都加10分,如何实现?
后来老师发现数学有一道题答案直接打印了,给每位学生的数学都减10分,如何实现?
============================================
#操作原型,期中
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语', 'python']
data = np.random.randint(0,150, size=(4,4,))
df1 = DataFrame(data=data, index=index, columns=columns)
df1
>>
语文 数学 英语 python
张三 42 136 84 48
李四 129 80 124 40
王五 50 86 72 147
赵六 5 39 83 15
#假设ddd是期中考试成绩,ddd2是期末考试成绩,请自由创建ddd2,并将其与ddd相加,求期中期末平均值。
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语', 'python']
data = np.random.randint(0,150, size=(4,4,))
df2 = DataFrame(data=data, index=index, columns=columns)
df2
>>
语文 数学 英语 python
张三 67 83 104 104
李四 67 97 25 144
王五 144 24 47 28
赵六 95 28 48 42
(df1 + df2) / 2
>>
语文 数学 英语 python
张三 71.0 78.0 130.5 42.0
李四 56.0 36.0 121.5 69.5
王五 102.0 23.0 88.5 82.5
赵六 89.0 54.5 82.0 97.5
#假设张三期中考试数学被发现作弊,要记为0分,如何实现?
df1.loc['张三','数学'] = 0
df1
>>
语文 数学 英语 python
张三 42 0 84 48
李四 129 80 124 40
王五 50 86 72 147
赵六 5 39 83 15
#李四因为举报张三作弊立功,期中考试所有科目加100分,如何实现?
df1.loc['李四'] + 100
df1
>>
语文 数学 英语 python
张三 42 0 84 48
李四 229 180 224 140
王五 50 86 72 147
赵六 5 39 83 15
#后来老师发现有一道题出错了,为了安抚学生情绪,给每位学生每个科目都加10分,如何实现?
df1 + 10
>>
语文 数学 英语 python
张三 52 10 94 58
李四 239 190 234 150
王五 60 96 82 157
赵六 15 49 93 25
#后来老师发现数学有一道题答案直接打印了,给每位学生的数学都减10分,如何实现?
df1['数学'] -= 10
df1
>>
语文 数学 英语 python
张三 42 -10 84 48
李四 229 170 224 140
王五 50 76 72 147
赵六 5 29 83 15
6. Pandas自带的DataFrame算术运算方法
pandas中自带一些DataFrame的运算方法
DataFrame.add : Add DataFrames.#加
DataFrame.sub : Subtract DataFrames.#减
DataFrame.mul : Multiply DataFrames.#乘
DataFrame.div : Divide DataFrames (float division).#除
DataFrame.truediv : Divide DataFrames (float division).
DataFrame.floordiv : Divide DataFrames (integer division).
DataFrame.mod : Calculate modulo (remainder after division).#取模
DataFrame.pow : Calculate exponential power.#指数幂
详细:7、数据分析/day05/day14/Pandas自带算术运算方法.ipynb
四、处理Pandas丢失数据
有两种丢失数据:
- None
- np.nan(NaN)
1. None
None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。
type(None)
>>NoneType
1 + '1'
>>TypeError: unsupported operand type(s) for +: 'int' and 'str'
n = np.array([1,2,3,None])
n
>>array([1, 2, 3, None], dtype=object)
n.sum()
>>TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
'''object类型的运算要比int类型的运算慢得多
计算不同数据类型求和时间
%timeit np.arange(1e5,dtype=xxx).sum()'''
%timeit np.arange(1e5,dtype='int').sum()
>>238 µs ± 27.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.arange(1e5,dtype='float').sum()
>>303 µs ± 18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit np.arange(1e5,dtype='object').sum()
12.5 ms ± 645 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2. np.nan(NaN)
np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。
但可以使用np.nan*()函数来计算nan,此时视nan为0。
type(np.nan)
>>floaat
n = np.array([1,2,3,np.nan])
n
>>array([ 1., 2., 3., nan])
n.sum()
>>nan
n.nansum(n)
>>6.0
3. pandas中的None与NaN
3.1 pandas中None与np.nan都视作np.nan
'''
创建DataFrame
使用DataFrame行索引与列索引修改DataFrame数据
'''
index = ['张三', '李四', '王五', '赵六']
columns = ['语文', '数学', '英语', 'python']
data = np.random.randint(0,150, size=(4,4,))
df1 = DataFrame(data=data, index=index, columns=columns)
df1
>>
语文 数学 英语 python
张三 120 22 58 55
李四 133 47 82 2
王五 18 114 44 132
赵六 83 119 139 44
# 不推荐的写法.
df1['语文']['张三'] = np.nan
# 正确的写法
df1.loc['张三', '数学'] = None
df1
>>
语文 数学 英语 python
张三 NaN NaN 89 135
李四 115.0 0.0 93 27
王五 73.0 29.0 94 116
赵六 1.0 23.0 61 57
3.2 删除数据(拓展)
#drop 删除
df1.drop(
labels=None,#指定要删除标签
axis=0,#指定是行还是列操作,默认为0,操作行
index=None,#指定删除的行
columns=None,#指定删除的列
level=None,
inplace=False,#是否修改原操作模型
errors='raise',
)
# 删除一行或者 一列数据
df1.drop(labels=['python'], axis=1, inplace=True)
>>
语文 数学 英语
张三 NaN NaN 58
李四 133.0 47.0 82
王五 18.0 114.0 44
赵六 83.0 119.0 139
df1.drop(index='赵六', columns='英语')
语文 数学
张三 NaN NaN
李四 133.0 47.0
王五 18.0 114.0
3.2 pandas中None与np.nan的操作
(1)判断函数
isnull()
notnull()
#整体判断
df1.isnull()/notnull()
pd.isnull/notnull(df1)
#isnull
语文 数学 英语 python
张三 True True False False
李四 False False False False
王五 False False False False
赵六 False False False False
# 检测行或者列是否存在缺失数据
# 检测行
df1.isnull().any(axis=1)
>>张三 True
李四 False
王五 False
赵六 False
dtype: bool
# 检测列
df1.isnull().any(axis=0)
语文 True
数学 True
英语 False
python False
dtype: bool
(2) 过滤、删除函数
#drop 删除
df1.drop(
labels=None,#指定要删除标签
axis=0,#指定是行还是列操作,默认为0,操作行
index=None,#指定删除的行
columns=None,#指定删除的列
level=None,
inplace=False,#是否修改原操作模型
errors='raise',
)
# 删除一行或者 一列数据
df1.drop(labels=['python'], axis=1, inplace=True)
>>
语文 数学 英语
张三 NaN NaN 58
李四 133.0 47.0 82
王五 18.0 114.0 44
赵六 83.0 119.0 139
df1.drop(index='赵六', columns='英语')
语文 数学
张三 NaN NaN
李四 133.0 47.0
王五 18.0 114.0
dd
# dropna删除缺失数据
df2.dropna(axis=0, #可以选择过滤的是行还是列(默认为行)
how='any', #也可以选择过滤的方式,any:任一;all:全部
thresh=None,
subset=None, #考虑的列标签,其他为NaN不考虑
inplace=False)
# 删除缺失数据
df2 = df1.copy()
df2.dropna(axis=1)
>>
英语
张三 58
李四 82
王五 44
赵六 139
df2
>>
语文 数学 英语
张三 NaN NaN NaN
李四 133.0 47.0 NaN
王五 18.0 114.0 44.0
赵六 83.0 119.0 NaN
df2.dropna(how='all')#全为NaN才删除
>>
语文 数学 英语
李四 133.0 47.0 NaN
王五 18.0 114.0 44.0
赵六 83.0 119.0 NaN
df2.dropna(subset=['语文', '数学'])#列标签为语文数学为NaN的才删除
>>
语文 数学 英语
李四 133.0 47.0 NaN
王五 18.0 114.0 44.0
赵六 83.0 119.0 NaN
(3) 填充函数 Series/DataFrame
fillna主要有2种用法:
第一种使用指定的值去填充.
df2.fillna(value=100)
第二种, 使用已有的值去填充.又分为向前填充,和向后填充.
# method : {'backfill', 'bfill', 'pad', 'ffill', None}
# limit限制连续填充的次数
df2.fillna(method='bfill', axis=0, limit=3)