算数运算和数据对齐
pandas一个强大的功能是,它可以对不同索引的对象进行算数运算。
s1 = pd.Series([1,2,3,4],index=['a','b','c','d'])
s1
'''
a 1
b 2
c 3
d 4
dtype: int64
'''
s2 = pd.Series([4,78,32,89,61],index=['a','b','e','d','g'])
s2
'''
a 4
b 78
e 32
d 89
g 61
dtype: int64
'''
#将两个Series相加
s1+s2
'''
a 5.0
b 80.0
c NaN
d 93.0
e NaN
g NaN
dtype: float64
'''
可以看到,对于两个对象相同的索引,值直接想加;对于不同的索引,引入了NaN值。
而对于DataFrame,只有当行索引和列索引都相同时,才会执行算数操作,否则引入NaN值。
data1 = pd.DataFrame(np.arange(9).reshape((3,3)),columns = list('bcd'),index = ['one','two','three'])
print("data1:")
print(data1)
print('\n')
data2 = pd.DataFrame(np.arange(12).reshape((4,3)),columns = list('bed'),index = ['one','second','three','four'])
print("data2:")
print(data2)
print('\n')
#相加
print("data1+data2:")
print(data1+data2)
'''
结果:
data1:
b c d
one 0 1 2
two 3 4 5
three 6 7 8
data2:
b e d
one 0 1 2
second 3 4 5
three 6 7 8
four 9 10 11
data1+data2:
b c d e
four NaN NaN NaN NaN
one 0.0 NaN 4.0 NaN
second NaN NaN NaN NaN
three 12.0 NaN 16.0 NaN
two NaN NaN NaN NaN
'''
但是往往我们希望能够出现数值而非NaN,这时有以下两种方法:
#采用add方法
data1 = pd.DataFrame(np.arange(9).reshape((3,3)),columns = list('bcd'),index = ['one','two','three'])
data2 = pd.DataFrame(np.arange(12).reshape((4,3)),columns = list('bed'),index = ['one','second','three','four'])
print(data1.add(data2,fill_value=0))
'''
结果:
b c d e
four 9.0 NaN 11.0 10.0
one 0.0 1.0 4.0 1.0
second 3.0 NaN 5.0 4.0
three 12.0 7.0 16.0 7.0
two 3.0 4.0 5.0 NaN
'''
显然地,这个结果没有达到预期。原因是data1和data2两个对象中,都有对方没有的索引。换句话说,它们之间没有包含关系。而add方法又是单向操作(姑且这么描述吧),没有办法通过add方法对这两个对象的索引进行全覆盖。
data1 = pd.DataFrame(np.arange(9).reshape((3,3)),columns = list('bcd'),index = ['one','two','three'])
data2 = pd.DataFrame(np.arange(12).reshape((4,3)),columns = list('bed'),index = ['one','two','three','four'])
print(data2.reindex(columns = data1.columns,fill_value=0))
'''
b c d
one 0 0 2
two 3 0 5
three 6 0 8
four 9 0 11
'''
通过重新索引可以对不同索引进行填充,但因为是单向操作,所以有些索引会丢失。
Series和DataFrame之间的运算
基本上,它们之间的运算会根据Series的索引匹配到DataFrame的列,并且沿着行一直向下广播,若存在不同索引,将会采用并集索引。
import pandas as pd
import numpy as np
data = pd.DataFrame(np.arange(16).reshape(4,4),
index=['one','two','three','four'],
columns=['first','second','third','forth'])
series = data.ix[0]
series
'''
first 0
second 1
third 2
forth 3
Name: one, dtype: int32
'''
data-series
结果如下:
*这里碰到一个之前没有注意的问题:DataFrame中直接索引访问的是列元素,访问行元素要用.ix元素(这里碰到报错,具体原因未知)
排序和排名
一般使用sort_index方法进行索引排序。
obj =pd. Series(range(4),index=['d','b','a','c'])
obj.sort_index()
'''
a 2
b 1
c 3
d 0
dtype: int64
'''
如果想要对值进行排序,则采用order方法:
*这里尝试的时候遇到一个问题,报错总是提示Series没有order属性,实在是苦恼.....
DataFrame方法同理,可以根据行索引(axis=0),也可通过列索引(axis=1)进行排序
上述默认排序为升序,可以采用降序,引入其ascending值(默认值为true,即升序)。
frame = pd.DataFrame(np.arange(8).reshape(2,4),index=['three','one'],columns=['d','a','b','c'])
frame
'''
d a b c
three 0 1 2 3
one 4 5 6 7
'''
frame.sort_index(axis=1,ascending=False)
结果为:
Data Frame按一个或多个列值排序引入by属性:
frame = pd.DataFrame({'b':[1,2,4,3],'c':[24,56,95,3]})
print(frame)
print("引入by属性:")
print(frame.sort_index(by='b'))
'''
b c
0 1 24
1 2 56
2 4 95
3 3 3
引入by属性:
b c
0 1 24
1 2 56
3 3 3
2 4 95
'''
Series和DataFrame的排名返回了一个Series或DataFrame,其中主要属性是method(破坏平级关系)。默认的method属性是取均值(对值相同的元素取排名均值):
a = pd.Series([3,5,2,7,3,4,9])
a.rank()
'''
0 2.5
1 5.0
2 1.0
3 6.0
4 2.5
5 4.0
6 7.0
dtype: float64
'''
也可以依照出现顺序排名,不取均值:
a = pd.Series([3,5,2,7,3,4,9])
a.rank(method='first')
'''
0 2.0
1 5.0
2 1.0
3 6.0
4 3.0
5 4.0
6 7.0
dtype: float64
'''
可以按照较大排名值排名:
a = pd.Series([3,5,2,7,3,4,9])
a.rank(method='max')
'''
0 3.0
1 5.0
2 1.0
3 6.0
4 3.0
5 4.0
6 7.0
dtype: float64
'''
按较小值排名用法相同,只要把max改成min就可以。
带有重复值的索引
python允许索引值相同,只是在选取时会将所有拥有这个索引的元素调用出来。
a = pd.Series([1,2,3,4],index=['a','b','a','d'])
a['a']
'''
a 1
a 3
dtype: int64
'''