Series和dataframe的运算

来自CloudWiki
跳转至: 导航搜索

简介

由于series与dataframe都是基于numpy的array数组构建而来的,因此他们的运算机制最大程度的沿用了数组运算中的广播机制

当然区别仍然存在,当不同的series或dataframe之间进行二元运算的时候,由于自定义索引的存在,索引对齐则更重要了

和常数之间的运算

series和常数运算

import numpy as np

import pandas as pd

a=pd.Series([2,1,4,5],index=["a","b","c","d"])

a

a    2
b    1
c    4
d    5
dtype: int64

和数值进行运算完全遵守numpy类似的规则:就是逐个作用到每一个元素

a*3

a     6
b     3
c    12
d    15
dtype: int64

np.exp(a)#无论是内部函数

a      7.389056
b      2.718282
c     54.598150
d    148.413159
dtype: float64

def w1(x):#还是自定义函数

   return x-9+2

print(w1(a))

a   -5
b   -6
c   -3
d   -2
dtype: int64

dataframe和常数运算

d=pd.DataFrame(np.random.randn(3,2),columns=["a","b"])

d

a 	b
0 	0.051766 	-0.744715
1 	0.572668 	2.354162
2 	0.660320 	0.505625

d-3

a 	b
0 	-2.948234 	-3.744715
1 	-2.427332 	-0.645838
2 	-2.339680 	-2.494375

同种类型之间的运算

由于dataframe等数据有了自定义索引,不像numpy的数组只有顺序索引,dataframe之间的运算是要求自定义索引对齐而不是隐式的顺序索引,因此numpy的广播机制在这里有所变化。

numpy的广播机制中,当两个数组维度不同的时候,会对某个维度进行整体复制是的维度匹配,这里相同索引之间的数据发生运算,找不到匹配索引的数据运算结果则为空值“nan”

当需要更改“nan”值的时候就需要用到pandas中的运算函数

运算符 pandas函数

+ 	add()
- 	sub()
* 	mul()
/ 	div()
// 	floordiv()
% 	mod()
** 	pow()

series间的运算

a=pd.Series([2,1,4,5],index=["a","b","c","d"])

a

a    2
b    1
c    4
d    5
dtype: int64

b=pd.Series([3,1,4,2,1],index=["a","b","c","j","p"])

b

a    3
b    1
c    4
j    2
p    1
dtype: int64

索引会取并集,找不到相同索引匹配进行运算的则为nan

a+b

a    5.0
b    2.0
c    8.0
d    NaN
j    NaN
p    NaN
dtype: float64

如果你希望缺失值用其他值来替代而不是空缺,则需要用函数来运算并加入fill_value参数

a.add(b,fill_value=0)

上面没找到匹配值的时候则用0来替代,注意加法运算之后数据类型都变为了float


a    5.0
b    2.0
c    8.0
d    5.0
j    2.0
p    1.0
dtype: float64

dataframe之间的运算

d=pd.DataFrame(np.random.randint(0,10,size=(3,2)),columns=["a","b"])

d

a 	b
0 	2 	6
1 	3 	5
2 	5 	8

c=pd.DataFrame(np.random.randint(0,10,size=(4,3)),columns=["a","b","c"])

c

a 	b 	c
0 	8 	0 	2
1 	7 	8 	7
2 	8 	6 	0
3 	6 	9 	1

d+c#不对应的列取NaN值

a 	b 	c
0 	10.0 	6.0 	NaN
1 	10.0 	13.0 	NaN
2 	13.0 	14.0 	NaN
3 	NaN 	NaN 	NaN


d.add(c,fill_value=0)#用函数,不对应的列也可以显示了

a    b    c
0  10.0  7.0  5.0
1  10.0  6.0  0.0
2   2.0  7.0  2.0
3   5.0  5.0  2.0

series与dataframe之间的运算

对于二维的dataframe来说,series只是相当于dataframe的一列(或是一行),要让两者发生运算基本继承了numpy广播机制,也就是进行横向或是纵向的复制,然后基于索引对齐进行匹配运算。

注意当广播之后仍然有匹配不到的索引则置空“nan”

(正常)纵向运算

a=pd.DataFrame(np.random.randint(0,10,size=(4,4)),columns=["a","b","c","d"])

a

a 	b 	c 	d
0 	9 	9 	7 	8
1 	3 	1 	3 	4
2 	0 	4 	9 	3
3 	3 	0 	0 	9

a.loc[0]

a    9
b    9
c    7
d    8
Name: 0, dtype: int32

a+a.loc[0]#运算默认的广播方向是纵向复制,

a 	b 	c 	d
0 	18 	18 	14 	16
1 	12 	10 	10 	12
2 	9 	13 	16 	11
3 	12 	9 	7 	17

(特殊)横向运算

a["b"]

0    9
1    1
2    4
3    0
Name: b, dtype: int32

a+a["b"]#总是将默认为一行,对应的索引为列标,这时如果序列和dataframe的列标不匹配,运算会发生错误

a 	b 	c 	d 	0 	1 	2 	3
0 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN
1 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN
2 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN
3 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN 	NaN

a.add(a["b"],axis=0)#如果需要横向复制则需要利用运算函数指定axis=0

a 	b 	c 	d
0 	18 	18 	16 	17
1 	4 	2 	4 	5
2 	4 	8 	13 	7
3 	3 	0 	0 	9

(特殊)行数或列数不一致

a.loc[0,::2]

a    9
c    7
Name: 0, dtype: int32

a+a.loc[0,::2]#当存在匹配不上的时候仍然会使用nan

a b c d 0 18.0 NaN 14.0 NaN 1 12.0 NaN 10.0 NaN 2 9.0 NaN 16.0 NaN 3 12.0 NaN 7.0 NaN