函数应用映射
numpy 的ufuncs(元素级数组方法) 也可以用来操作pandas对象
frame = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
index=['one', 'two', 'three', 'four']
)
print(np.abs(frame))
# b d e
# one 0.0 1.0 2.0
# two 3.0 4.0 5.0
# three 6.0 7.0 8.0
# four 9.0 10.0 11.0
abs 是应用到每一个元素, 也可以应用到每一行或者每一列
将函数应用到各行各列所形成的以为数组。DataFrame apply 方法可以实现这样的功能
下面来瞅瞅
fun = lambda x: x.max() - x.min()
print(frame.apply(fun)) # 应用到行
# b 9.0
# d 9.0
# e 9.0
# dtype: float64
print(frame.apply(fun, axis=1)) # 应用到列
# one 2.0
# two 2.0
# three 2.0
# four 2.0
# dtype: float64
除了标量值之外, 传递给apply的函数还可以返回由多个值组成的series
def f(x):
return Series([x.min(), x.max()], index=['min', 'max'])
print(frame.apply(f))
元素级别的Python 函数也是可以用。 例如如果你想得到frame中的各个浮点值的格式化字符串, 使用applymap
fo = lambda x: '%.3f' %x
print(frame.applymap(fo))
# b d e
# one 0.000 1.000 2.000
# two 3.000 4.000 5.000
# three 6.000 7.000 8.000
# four 9.000 10.000 11.000
排序和排名
根据条件多数据集进行排序。 要对行和列索引进行排序(按照字典顺序),可以使用sort_index 方法, 他将返回一个已经排序的新对象(是新新对象哦)
frame = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
index=['one', 'two', 'three', 'four']
)
obj = Series(range(4), index=['d', 'a', 'c', 'b'])
print(obj.sort_index())
# a 1
# b 3
# c 2
# d 0
# dtype: int64
print("===")
print(obj.sort_values())
# d 0
# a 1
# c 2
# b 3
# dtype: int64
对于DataFrame, 则可以根据任意一个轴上的索引进行排序
frame = DataFrame(np.arange(8).reshape((2, 4)), index=['three', 'one'],
columns=['d', 'a', 'b', 'c']
)
print(frame.sort_index())
# d a b c
# one 4 5 6 7
# three 0 1 2 3
print("=====")
print(frame.sort_index(axis=1))
# a b c d
# three 1 2 3 0
# one 5 6 7 4
print("==========")
print(frame.sort_index(axis=1, ascending=False)) # 默认升序, 也可以是降序
# d c b a
# three 0 3 2 1
# one 4 7 6 5
排序时候任何缺失值, 默认都会被放在Series的末尾
obj = Series([4, np.nan, 7, np.nan, -3, 2])
print(obj.sort_values())
#4 -3.0
#5 2.0
#0 4.0
#2 7.0
#1 NaN
#3 NaN
#dtype: float64
DataFrame 可以根据一个或者多个列进行排序, 将一个或者多个列的名字传递给by。
frame = DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
print(frame)
# a b
# 0 0 4
# 1 1 7
# 2 0 -3
# 3 1 2
print("=========")
print(frame.sort_values(by="b"))
# a b
# 2 0 -3
# 3 1 2
# 0 0 4
# 1 1 7
print("========")
print(frame.sort_values(by=['a', 'b'])) # 先根据a a 相同再根据b
# a b
# 2 0 -3
# 0 0 4
# 3 1 2
# 1 1 7
根据多列进行排序的时候, 有点像 内置类 operator 差不多
from operator import itemgetter
sorted(obj, key=itemgetter('a', 'b'))
排名
默认是有一个从小的的排序然后排名。她会增设一个排名值(从1开始, 一直到数组中有序数据的数量), 她可以根据某种规则破坏平级关系。rank 是通过 各组分配一个平均排名 的方式破坏平级关系
先来看下series 的排名
obj = Series([7, -5, 7, 4, 2, 0, 4])
print(obj.rank())
# 0 6.5
# 1 1.0
# 2 6.5
# 3 4.5
# 4 3.0
# 5 2.0
# 6 4.5
# dtype: float64
现在分析
首先对数据进行排序
-5 0 2 4 4 7 7
看算法
-5 1/1 = 1 -5 排在第一个 且只有一个数据
0 2 /1 = 2 2 排在第二位 且只有一个数据
2 3/ 1 =3 3 排在第三位且只有一个数据
4 (4+5)/2 =4.5 4 排在第 4 和5 位 有两个数据
4 (4+5)/2 =4.5 4 排在第 4 和5 位 有两个数据
7 (6+7) /2 =6.5 7 排在第6 和7位 有两个数据
7 (6+7) /2 =4.5 7 排在第6 和7位 有两个数据
可以根据值在原数据中出现的排序给予排名
在上面基础之上
obj = Series([7, -5, 7, 4, 2, 0, 4])
print(obj.rank(method='first'))
# 0 6.0
# 1 1.0
# 2 7.0
# 3 4.0
# 4 3.0
# 5 2.0
# 6 5.0
分析: 先对排序排序看他的位置, 输出的是值排序后的
-5 原始排序位于第1个元素 1
0 2
2 3
4 4
4 5
7 6
7 7
然后输出就对应着具体顺序给输出
这里有几个
这几个方法 使用分组字眼的话就会 相同的合并
按照降序进行排名 默认是升序的, 都是依赖于排序的排名
print(obj.rank(method='max', ascending=False))
# 0 2.0
# 1 7.0
# 2 2.0
# 3 4.0
# 4 5.0
# 5 6.0
# 6 4.0
# dtype: float64
DataFrame 上面进行 行列不同的排名
frame.rank()
frame.rank(axis=1)
带有重复值的索引
前面的都是带有唯一的轴标签。 在pandas 中的并不是强制的。
obj = Series(range(5), index=['a', 'a', 'b', 'b', 'b'])
print(obj)
# a 0
# a 1
# b 2
# b 3
# b 4
# dtype: int64
注意点:
带有重复值的引值, 数据选取的行为将会有不同。如果某个索引对应多个值, 则返回一个Series, 但是对应一个单个值这返回一个标量值
obj = Series([7, -5, 7, 4, 2, 0, 4])
obj = Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
print(obj['a'])
#a 0
#a 1
#dtype: int64
print(obj['c']) # 4
在Dataframe 同样也适合这样的规则
df = DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])
print(df)
# 0 1 2
#a -1.131963 -0.449609 0.472020
#a -0.167403 0.399746 -0.831750
#b 0.324949 0.074558 0.503937
#b 0.338922 1.924908 0.841473
print(df.ix['a'])
# 0 1 2
#a -0.198498 -0.778882 -2.029625
#a -1.301808 2.063084 -1.239879
汇总和计算描述统计
计算时候可以忽略缺失值 Na
DataFrame 的sum方法会返回一个含有列小计的Series
print(df.sum())
#one 9.25
#two -5.80
#dtype: float64
print(df.sum(axis=1))
#a 1.40
#b 2.60
#c 0.00
#d -0.55
#dtype: float64
NA 值会被排除, 除非整个切片都是NA, 通过skipna 选项可以禁用这个功能
print(df.mean())
#one 3.083333
#two -2.900000
#dtype: float64
print("=====")
print(df.mean(axis=1, skipna=False))
#a NaN
#b 1.300
#c NaN
#d -0.275
#dtype: float64
idxmax, idxmin 返回的是间接统计(比如达到最大值或者最小值的索引)
print(df.idxmax())
# one b
# two d
# dtype: object
print(df.idxmin())
# one d
# two b
# dtype: object
print(df.cumsum())
# one two
# a 1.40 NaN
# b 8.50 -4.5
# c NaN NaN
# d 9.25 -5.8
唯一值, 值计数以及成员资格
得到唯一值
obj = Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
print(obj.unique())
#['c' 'a' 'd' 'b']
按照出现的频率排序
print(obj.value_counts())
#a 3
#c 3
#b 2
#d 1
频率出来但是不排序
print(pd.value_counts(obj.values))
# a 3
# c 3
# b 2
# d 1
# dtype: int64
print("======")
print(pd.value_counts(obj.values, sort=False))
# b 2
# c 3
# a 3
# d 1
# dtype: int64
isin 判断矢量化集合的成员资格, 可用于选取Series中或者DataFrame列中数据的子集
mask = obj.isin(['c', 'b'])
print(mask)
# 0 True
# 1 False
# 2 False
# 3 False
# 4 False
# 5 True
# 6 True
# 7 True
# 8 True
# dtype: bool
print("=======")
print(obj[mask])
# 0 c
# 5 b
# 6 b
# 7 c
# 8 c
# dtype: object
处理缺失值 (重头戏呀)
isnull 可以检查的出来
data = Series(['one', 'two', np.nan, 'three'])
print(data)
# 0 one
# 1 two
# 2 NaN
# 3 three
# dtype: object
print("=======")
print(data.isnull())
# 0 False
# 1 False
# 2 True
# 3 False
# dtype: bool
过滤掉缺失数据
from numpy import nan as NA
data = Series([1, NA, 3.5, NA, 7])
print(data)
# 0 1.0
# 1 NaN
# 2 3.5
# 3 NaN
# 4 7.0
# dtype: float64
print(data.dropna())
# 0 1.0
# 2 3.5
# 4 7.0
# dtype: float64
# 通过布尔型索引就 也是可以达到的
print(data[data.notnull()])
0 1.0
2 3.5
4 7.0
dtype: float64
上面是处理series的确实数据, 现在来看DataFrame 的
from numpy import nan as NA
data = DataFrame([
[1., 6.5, 3],
[1., NA, NA],
[NA, NA, NA],
[NA, 6.5, 3.]
])
DataFrame 默认丢失含有任何NA 缺失值的行
cleaned = data.dropna()
print(cleaned)
# 0 1 2
#0 1.0 6.5 3.0
传入how=’all’ 丢弃所有为NA 缺失值的行
print(data.dropna(how='all'))
# 0 1 2
#0 1.0 6.5 3.0
#1 1.0 NaN NaN
#3 NaN 6.5 3.0
丢弃列上面的NA 缺失值
print(data.dropna(axis=1, how='all'))
# 0 1 2
#0 1.0 6.5 3.0
#1 1.0 NaN NaN
#2 NaN NaN NaN
#3 NaN 6.5 3.0
填充数据
上面讲的是过滤掉缺失值, 如果不想过滤的话可以填充
。 fillna 方法是最主要的函数, 将缺失值替换为常量值。
print(data.fillna(0))
# 0 1 2
# 0 1.0 6.5 3.0
# 1 1.0 0.0 0.0
# 2 0.0 0.0 0.0
# 3 0.0 6.5 3.0
通过字典调用fillna 就可以实现对不同的列填充不同的值
print(data.fillna({0: 33, 2: 99}))
# 0 1 2
# 0 1.0 6.5 3.0
# 1 1.0 NaN 99.0
# 2 33.0 NaN 99.0
# 3 33.0 6.5 3.0
像上面都是直接打印, 说明返回的是一个新的对象, 也是可以对现有对象进行就地修改
data.fillna(100, inplace=True)
print(data)
# 0 1 2
#0 1.0 6.5 3.0
#1 1.0 100.0 100.0
#2 100.0 100.0 100.0
#3 100.0 6.5 3.0
层次化索引
让你能在一个轴上面拥有多个索引级别。抽象说就是使你能以低纬度形式处理高纬度数据。
data = Series(np.random.randn(10),
index=[
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd', ],
[1, 2, 3, 1, 2, 3, 1, 2, 2, 3]
]
)
print(data)
# a 1 -1.137407
# 2 -0.816179
# 3 1.445783
# b 1 0.829613
# 2 0.229386
# 3 -0.298677
# c 1 0.845615
# 2 -0.156037
# d 2 -1.540562
# 3 -0.362225
# dtype: float64
这样看结构可能还不太好理解, 现在给unstack 一下 将这个series 安排进Datafram中
print(data.unstack())
# 1 2 3
# a -1.137407 -0.816179 1.445783
# b 0.829613 0.229386 -0.298677
# c 0.845615 -0.156037 NaN
# d NaN -1.540562 -0.362225
对比着这两个输出结构 可以看成a 是外城内层就是对应的各个列
这里有个可能更好理解的
对于层次化索引的对象, 选取数据的子集的操作很是简单
print(data['b'])
# 1 0.829613
# 2 0.229386
# 3 -0.298677
# dtype: float64
print(data['b':'c'])
# b 1 0.829613
# 2 0.229386
# 3 -0.298677
# c 1 0.845615
# 2 -0.156037
# dtype: float64
print(data.ix[['b', 'd']])
# b 1 0.829613
# 2 0.229386
# 3 -0.298677
# d 2 -1.540562
# 3 -0.362225
# dtype: float64
在内层进行选取
print(data[:, 2])
# a -0.816179
# b 0.229386
# c -0.156037
# d -1.540562
# dtype: float64