Series和dataframe的运算
目录
简介
由于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