- 4.1 The NumPy ndarray 多维数组对象
- 4.2 Universal Functions 通用函数
- 4.3 Array-Oriented Programming with Arrays 数组导向编程
- 5.1 Introduction to pandas Data Structures pandas 的数据结构
- 5.2 Essential Functionality 主要功能
- 5.3 Summarizing and Computing Descriptive Statistics 汇总和描述性统计
- 7.1 Handling Missing Data 处理缺失数据
- 7.2 Data Transformation 数据变换
- 7.3 String Manipulation 字符串处理
- 11.1 Date and Time Data Types and Tools 日期和时间数据类型及其工具
- 11.2 Time Series Basics 时间序列基础
- 11.3 Date Ranges, Frequencies, and Shifting 日期范围,频度,和位移
- 12.1 Categorical Data 类别数据
- 14.1 USA.gov Data from Bitly USA.gov 数据集
- 14.2 MovieLens 1M Dataset MovieLens 1M 数据集
- 14.3 US Baby Names 1880–2010 1880年至2010年美国婴儿姓名
5.2 Essential Functionality 主要功能
接下来介绍 pandas 中的一些主要功能,这里只介绍一些经常用到的。
1 Reindexing(重新索引)
pandas 中一个重要的方法是 reindex,已实施在创建 object 的时候遵照一个新的 index。如下例:
import pandas as pd
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c']) obj
d 4.5 b 7.2 a -5.3 c 3.6 dtype: float64
在 series 上调用 reindex 能更改 index,如果没有对应 index 的话会引入缺失数据:
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e']) obj2
a -5.3 b 7.2 c 3.6 d 4.5 e NaN dtype: float64
在处理时间序列这样的数据时,我们可能需要在 reindexing 的时候需要修改值。method 选项能做到这一点,比如设定 method 为 ffill:
obj3 = pd.Series(['bule', 'purple', 'yellow'], index=[0, 2, 4]) obj3
0 bule 2 purple 4 yellow dtype: object
obj3.reindex(range(6), method='ffill')
0 bule 1 bule 2 purple 3 purple 4 yellow 5 yellow dtype: object
对于 DataFrame,reindex 能更改 row index,或 column index。reindex the rows:
import numpy as np
frame = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California'])
frame
Ohio | Texas | California | |
---|---|---|---|
a | 0 | 1 | 2 |
c | 3 | 4 | 5 |
d | 6 | 7 | 8 |
frame2 = frame.reindex(['a', 'b', 'c', 'd']) frame2
Ohio | Texas | California | |
---|---|---|---|
a | 0.0 | 1.0 | 2.0 |
b | NaN | NaN | NaN |
c | 3.0 | 4.0 | 5.0 |
d | 6.0 | 7.0 | 8.0 |
更改 columns index:
states = ['Texas', 'Utah', 'California']
frame.reindex(columns=states)
Texas | Utah | California | |
---|---|---|---|
a | 1 | NaN | 2 |
c | 4 | NaN | 5 |
d | 7 | NaN | 8 |
还可以使用 loc 更简洁的 reindex:
frame.loc[['a', 'b', 'c', 'd'], states]
Texas | Utah | California | |
---|---|---|---|
a | 1.0 | NaN | 2.0 |
b | NaN | NaN | NaN |
c | 4.0 | NaN | 5.0 |
d | 7.0 | NaN | 8.0 |
2 Dropping Entries from an Axis (按轴删除记录)
对于 series,drop 回返回一个新的 object,并删去你制定的 axis 的值:
obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e']) obj
a 0.0 b 1.0 c 2.0 d 3.0 e 4.0 dtype: float64
new_obj = obj.drop('c') new_obj
a 0.0 b 1.0 d 3.0 e 4.0 dtype: float64
obj.drop(['d', 'c'])
a 0.0 b 1.0 e 4.0 dtype: float64
对于 DataFrame,index 能按行或列的 axis 来删除:
data = pd.DataFrame(np.arange(16).reshape(4, 4), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four']) data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
行处理:如果 a sequence of labels(一个标签序列)来调用 drop,会删去 row labels(axis 0):
data.drop(['Colorado', 'Ohio'])
one | two | three | four | |
---|---|---|---|---|
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
列处理:drop 列的话,设定 axis=1 或 axis='columns':
data.drop('two', axis=1)
one | three | four | |
---|---|---|---|
Ohio | 0 | 2 | 3 |
Colorado | 4 | 6 | 7 |
Utah | 8 | 10 | 11 |
New York | 12 | 14 | 15 |
data.drop(['two', 'four'], axis='columns')
one | three | |
---|---|---|
Ohio | 0 | 2 |
Colorado | 4 | 6 |
Utah | 8 | 10 |
New York | 12 | 14 |
drop 也可以不返回一个新的 object,而是直接更改 series or dataframe in-place:
obj.drop('c', inplace=True) obj
a 0.0 b 1.0 d 3.0 e 4.0 dtype: float64
3 Indexing, Selection, and Filtering(索引,选择,过滤)
series indexing(obj[...]) 相当于 numpy 的 array indexing, 而且除了整数,还可以使用 series 的 index:
obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd']) obj
a 0.0 b 1.0 c 2.0 d 3.0 dtype: float64
obj['b']
1.0
obj[1]
1.0
obj[2:4]
c 2.0 d 3.0 dtype: float64
# 选中行 obj[['b', 'a', 'd']]
b 1.0 a 0.0 d 3.0 dtype: float64
obj[[1, 3]]
b 1.0 d 3.0 dtype: float64
obj[obj < 2]
a 0.0 b 1.0 dtype: float64
用 label 来 slicing(切片)的时候,和 python 的切片不一样的在于,会包括尾节点:
obj['b':'c']
b 1.0 c 2.0 dtype: float64
可以直接给选中的 label 更改值:
obj['b':'c'] = 5 obj
a 0.0 b 5.0 c 5.0 d 3.0 dtype: float64
而对于 DataFrame,indexing 可以通过一个值或序列,选中一个以上的列:
data = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four']) data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
data['two']
Ohio 1 Colorado 5 Utah 9 New York 13 Name: two, dtype: int64
data[['three', 'one']]
three | one | |
---|---|---|
Ohio | 2 | 0 |
Colorado | 6 | 4 |
Utah | 10 | 8 |
New York | 14 | 12 |
dataframe 的 indexing 有一些比较特别的方式。比如通过布尔数组:
data[:2]
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 1 | 2 | 3 |
Colorado | 4 | 5 | 6 | 7 |
data[data['three'] > 5]
one | two | three | four | |
---|---|---|---|---|
Colorado | 4 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
行选择的语法格式 data[:2]
是很方便的。给 []
里传入一个 list 的话,可以选择列。
另一种方法是用 boolean dataframe:
data < 5
one | two | three | four | |
---|---|---|---|---|
Ohio | True | True | True | True |
Colorado | True | False | False | False |
Utah | False | False | False | False |
New York | False | False | False | False |
data[data < 5] = 0 data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 0 | 0 | 0 |
Colorado | 0 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
Selection with loc and iloc(用 loc 和 iloc 来选择)
对于 label-indexing on rows, 我们介绍特别的索引符,loc and iloc. 这两个方法能通过 axis labels(loc)或 integer(iloc),来选择行或列。
一个列子,选中一行多列 by label:
data
one | two | three | four | |
---|---|---|---|---|
Ohio | 0 | 0 | 0 | 0 |
Colorado | 0 | 5 | 6 | 7 |
Utah | 8 | 9 | 10 | 11 |
New York | 12 | 13 | 14 | 15 |
data.loc['Colorado', ['two', 'three']]
two 5 three 6 Name: Colorado, dtype: int64
同 iloc 实现相同的效果:
data.iloc[2, [3, 0, 1]]
four 11 one 8 two 9 Name: Utah, dtype: int64
data.iloc[2] # 一行
one 8 two 9 three 10 four 11 Name: Utah, dtype: int64
data.iloc[[1, 2], [3, 0, 1]]
four | one | two | |
---|---|---|---|
Colorado | 7 | 0 | 5 |
Utah | 11 | 8 | 9 |
indexing 函数也能用于切片,不论是 single labels 或 lists of labels:
data.loc[:'Utah', 'two']
Ohio 0 Colorado 5 Utah 9 Name: two, dtype: int64
data.iloc[:, :3][data.three > 5]
one | two | three | |
---|---|---|---|
Colorado | 0 | 5 | 6 |
Utah | 8 | 9 | 10 |
New York | 12 | 13 | 14 |
pandas 中有很多用于选择和重新选择数据的方法。
注意:当设计 padnas 的时候,作者发现 frame[:, col]这样的语法是比较冗长的,因为这是会被经常用到的一个功能。作者把一些 indexing 的功能(lable or integer)集成在了 ix 这个方法上。实际中,因为这种 label 和 integer 都可以用的方式很方便,于是 pandas team 设计了 loc 和 ilco 来实现 label-based 和 integer-based indexing.
虽然 ix indexing 依然错在,但是已经过时,不推荐使用。
4 Integer Indexes(整数索引)
一些新手再用 integer 来 index 的时候,总是会被绊倒。因为这种方法和 python 用于 list 和 tuple 的 indexing 方法不同。
比如,你不希望下面的代码出现 error:
ser = pd.Series(np.arange(3.))
ser
0 0.0 1 1.0 2 2.0 dtype: float64
ser[-1]
看到了,pandas 在整数索引上可能会出错。这里我们有一个 index 包括 0,1,2,但是猜测用户想要什么是很困难的:
ser
0 0.0 1 1.0 2 2.0 dtype: float64
另一方面,如果用非整数来做 index,就没有歧义了:
ser2 = pd.Series(np.arange(3.), index=['a', 'b', 'c']) ser2[-1]
2.0
为了保持连贯性,如果 axis index 里包含 integer,那么选择数据的时候,就会是 label-orented. 为了更精确地选择,使用 loc
(for label)或 ilco
(for integers):
ser[:1]
0 0.0 dtype: float64
ser.loc[:1]
0 0.0 1 1.0 dtype: float64
ser.iloc[:1]
0 0.0 dtype: float64
5 Arithmetic and Data Alignment (算数和数据对齐)
pandas 一个有用的 feature 就是,不同 index 的 obejct 之间的算数计算。如果两个 object 相加,但他们各自的 index 并不相同,最后结果得到的 index 是这两个 index 的合集:
s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([2.1, 3.6, -1.5, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])
s1
a 7.3 c -2.5 d 3.4 e 1.5 dtype: float64
s2
a 2.1 c 3.6 e -1.5 f 4.0 g 3.1 dtype: float64
s1 + s2
a 9.4 c 1.1 d NaN e 0.0 f NaN g NaN dtype: float64
这种数据对齐的方式(internal data alignment)引入了很多缺失值在没有陈赫的位置上。这些缺失值会被用在之后的算数计算中。
在 DataFrame 中,数据对齐同时发生在行和列上:
df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'), index=['Ohio', 'Texas', 'Colorado'])
df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
df1
b | c | d | |
---|---|---|---|
Ohio | 0.0 | 1.0 | 2.0 |
Texas | 3.0 | 4.0 | 5.0 |
Colorado | 6.0 | 7.0 | 8.0 |
df2
b | d | e | |
---|---|---|---|
Utah | 0.0 | 1.0 | 2.0 |
Ohio | 3.0 | 4.0 | 5.0 |
Texas | 6.0 | 7.0 | 8.0 |
Oregon | 9.0 | 10.0 | 11.0 |
相加的结果就是两个 DataFrame,行和列的合集:
df1 + df2
b | c | d | e | |
---|---|---|---|---|
Colorado | NaN | NaN | NaN | NaN |
Ohio | 3.0 | NaN | 6.0 | NaN |
Oregon | NaN | NaN | NaN | NaN |
Texas | 9.0 | NaN | 12.0 | NaN |
Utah | NaN | NaN | NaN | NaN |
因为'c'和'e'列都不在两个 DataFrame 里,所有全是缺失值。对于行,即使有相同的,但列不一样的话也会是缺失值。
如果两个 DataFrame 相加,而且没有 column 和 row,结果会全是 null:
df1 = pd.DataFrame({'A': [1, 2]}) df2 = pd.DataFrame({'B': [3, 4]})
df1
A | |
---|---|
0 | 1 |
1 | 2 |
df2
B | |
---|---|
0 | 3 |
1 | 4 |
df1 - df2
A | B | |
---|---|---|
0 | NaN | NaN |
1 | NaN | NaN |
Arithmetic methods with fill values (带填充值的算数方法)
对于上面那些缺失值,我们想要填上 0:
df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd')) df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde')) df2.loc[1, 'b'] = np.nan
df1
a | b | c | d | |
---|---|---|---|---|
0 | 0.0 | 1.0 | 2.0 | 3.0 |
1 | 4.0 | 5.0 | 6.0 | 7.0 |
2 | 8.0 | 9.0 | 10.0 | 11.0 |
df2
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0.0 | 1.0 | 2.0 | 3.0 | 4.0 |
1 | 5.0 | NaN | 7.0 | 8.0 | 9.0 |
2 | 10.0 | 11.0 | 12.0 | 13.0 | 14.0 |
3 | 15.0 | 16.0 | 17.0 | 18.0 | 19.0 |
不使用添加方法的结果:
df1 + df2
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0.0 | 2.0 | 4.0 | 6.0 | NaN |
1 | 9.0 | NaN | 13.0 | 15.0 | NaN |
2 | 18.0 | 20.0 | 22.0 | 24.0 | NaN |
3 | NaN | NaN | NaN | NaN | NaN |
使用 fill_value:
df1.add(df2, fill_value=0)
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0.0 | 2.0 | 4.0 | 6.0 | 4.0 |
1 | 9.0 | 5.0 | 13.0 | 15.0 | 9.0 |
2 | 18.0 | 20.0 | 22.0 | 24.0 | 14.0 |
3 | 15.0 | 16.0 | 17.0 | 18.0 | 19.0 |
每一个都有一个配对的,以 r 开头,意思是反转:
1 / df1
a | b | c | d | |
---|---|---|---|---|
0 | inf | 1.000000 | 0.500000 | 0.333333 |
1 | 0.250000 | 0.200000 | 0.166667 | 0.142857 |
2 | 0.125000 | 0.111111 | 0.100000 | 0.090909 |
df1.rdiv(1)
a | b | c | d | |
---|---|---|---|---|
0 | inf | 1.000000 | 0.500000 | 0.333333 |
1 | 0.250000 | 0.200000 | 0.166667 | 0.142857 |
2 | 0.125000 | 0.111111 | 0.100000 | 0.090909 |
在 reindex(重建索引)的时候,也可以使用 fill_value:
df1.reindex(columns=df2.columns, fill_value=0)
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 0.0 | 1.0 | 2.0 | 3.0 | 0 |
1 | 4.0 | 5.0 | 6.0 | 7.0 | 0 |
2 | 8.0 | 9.0 | 10.0 | 11.0 | 0 |
Operations between DataFrame and Series (DataFrame 和 Series 之间的操作)
先举个 numpy 的例子帮助理解,可以考虑成一个二维数组和它的一行:
arr = np.arange(12.).reshape((3, 4)) arr
array([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]])
arr[0]
array([ 0., 1., 2., 3.])
arr - arr[0]
array([[ 0., 0., 0., 0.], [ 4., 4., 4., 4.], [ 8., 8., 8., 8.]])
可以看到,这个减法是用在了每一行上。这种操作叫 broadcasting,在 Appendix A 有更详细的解释。DataFrame 和 Series 的操作也类似:
frame = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon']) series = frame.iloc[0]
frame
b | d | e | |
---|---|---|---|
Utah | 0.0 | 1.0 | 2.0 |
Ohio | 3.0 | 4.0 | 5.0 |
Texas | 6.0 | 7.0 | 8.0 |
Oregon | 9.0 | 10.0 | 11.0 |
series
b 0.0 d 1.0 e 2.0 Name: Utah, dtype: float64
可以理解为 series 的 index 与 dataframe 的列匹配,broadcasting down the rows(向下按行广播):
frame - series
b | d | e | |
---|---|---|---|
Utah | 0.0 | 0.0 | 0.0 |
Ohio | 3.0 | 3.0 | 3.0 |
Texas | 6.0 | 6.0 | 6.0 |
Oregon | 9.0 | 9.0 | 9.0 |
如果一个 index 既不在 DataFrame 的 column 中,也不再 series 里的 index 中,那么结果也是合集:
series2 = pd.Series(range(3), index=['b', 'e', 'f']) frame + series2
b | d | e | f | |
---|---|---|---|---|
Utah | 0.0 | NaN | 3.0 | NaN |
Ohio | 3.0 | NaN | 6.0 | NaN |
Texas | 6.0 | NaN | 9.0 | NaN |
Oregon | 9.0 | NaN | 12.0 | NaN |
如果想要广播列,去匹配行,必须要用到算数方法:
series3 = frame['d'] frame
b | d | e | |
---|---|---|---|
Utah | 0.0 | 1.0 | 2.0 |
Ohio | 3.0 | 4.0 | 5.0 |
Texas | 6.0 | 7.0 | 8.0 |
Oregon | 9.0 | 10.0 | 11.0 |
series3
Utah 1.0 Ohio 4.0 Texas 7.0 Oregon 10.0 Name: d, dtype: float64
frame.sub(series3, axis='index')
b | d | e | |
---|---|---|---|
Utah | -1.0 | 0.0 | 1.0 |
Ohio | -1.0 | 0.0 | 1.0 |
Texas | -1.0 | 0.0 | 1.0 |
Oregon | -1.0 | 0.0 | 1.0 |
axis 参数就是用来匹配轴的。在这个例子里是匹配 dataframe 的 row index( axis='index
or axis=0
),然后再广播。
6 Function Application and Mapping (函数应用和映射)
numpy 的 ufuncs(element-wise 数组方法)也能用在 pandas 的 object 上:
frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon']) frame
b | d | e | |
---|---|---|---|
Utah | -0.810435 | 0.194448 | -0.705901 |
Ohio | -0.886275 | 0.553640 | 1.066754 |
Texas | 0.189898 | -0.056108 | -0.159926 |
Oregon | 0.448303 | 0.439650 | -1.351029 |
np.abs(frame)
b | d | e | |
---|---|---|---|
Utah | 0.810435 | 0.194448 | 0.705901 |
Ohio | 0.886275 | 0.553640 | 1.066754 |
Texas | 0.189898 | 0.056108 | 0.159926 |
Oregon | 0.448303 | 0.439650 | 1.351029 |
另一个常用的操作是把一个用在一维数组上的函数,应用在一行或一列上。要用到 DataFrame 中的 apply 函数:
f = lambda x: x.max() - x.min() frame.apply(f)
b 1.334579 d 0.609748 e 2.417783 dtype: float64
这里函数 f,计算的是一个 series 中最大值和最小值的差,在 frame 中的每一列,这个函数被调用一次。作为结果的 series,它的 index 就是 frame 的 column。
如果你传入 axis='column'
用于 apply,那么函数会被用在每一行:
frame.apply(f, axis='columns')
Utah 1.004883 Ohio 1.953030 Texas 0.349825 Oregon 1.799333 dtype: float64
像是 sum, mean 这样的数组统计方法,DataFrame 中已经集成了,所以没必要用 apply。
apply 不会返回标量,只会返回一个含有多个值的 series:
def f(x): return pd.Series([x.min(), x.max()], index=['min', 'max'])
frame
b | d | e | |
---|---|---|---|
Utah | -0.810435 | 0.194448 | -0.705901 |
Ohio | -0.886275 | 0.553640 | 1.066754 |
Texas | 0.189898 | -0.056108 | -0.159926 |
Oregon | 0.448303 | 0.439650 | -1.351029 |
frame.apply(f)
b | d | e | |
---|---|---|---|
min | -0.886275 | -0.056108 | -1.351029 |
max | 0.448303 | 0.553640 | 1.066754 |
element-wise 的 python 函数也能用。假设想要格式化 frame 中的浮点数,变为 string。可以用 apply map:
format = lambda x: '%.2f' % x
frame.applymap(format)
b | d | e | |
---|---|---|---|
Utah | -0.81 | 0.19 | -0.71 |
Ohio | -0.89 | 0.55 | 1.07 |
Texas | 0.19 | -0.06 | -0.16 |
Oregon | 0.45 | 0.44 | -1.35 |
applymap 的做法是,series 有一个 map 函数,能用来实现 element-wise 函数:
frame['e'].map(format)
Utah -0.71 Ohio 1.07 Texas -0.16 Oregon -1.35 Name: e, dtype: object
7 Sorting and Ranking (排序)
按 row 或 column index 来排序的话,可以用 sort_index 方法,会返回一个新的 object:
obj = pd.Series(range(4), index=['d', 'a', 'b', 'c']) obj.sort_index()
a 1 b 2 c 3 d 0 dtype: int64
在 DataFrame,可以用 index 或其他 axis 来排序:
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()
d | a | b | c | |
---|---|---|---|---|
one | 4 | 5 | 6 | 7 |
three | 0 | 1 | 2 | 3 |
frame.sort_index(axis=1)
a | b | c | d | |
---|---|---|---|---|
three | 1 | 2 | 3 | 0 |
one | 5 | 6 | 7 | 4 |
默认是升序,可以设置降序:
frame.sort_index(axis=1, ascending=False)
d | c | b | a | |
---|---|---|---|---|
three | 0 | 3 | 2 | 1 |
one | 4 | 7 | 6 | 5 |
通过值来排序,用 sort_values 方法:
obj = pd.Series([4, 7, -3, 2]) obj.sort_values()
2 -3 3 2 0 4 1 7 dtype: int64
缺失值会被排在最后:
obj = pd.Series([4, np.nan, 7, np.nan, -3, 2]) obj.sort_values()
4 -3.0 5 2.0 0 4.0 2 7.0 1 NaN 3 NaN dtype: float64
对于一个 DataFrame,可以用一列或多列作为 sort keys。这样的话,只需要把一列多多列的名字导入到 sort_values 即可:
frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]}) frame
a | b | |
---|---|---|
0 | 0 | 4 |
1 | 1 | 7 |
2 | 0 | -3 |
3 | 1 | 2 |
frame.sort_values(by='b')
a | b | |
---|---|---|
2 | 0 | -3 |
3 | 1 | 2 |
0 | 0 | 4 |
1 | 1 | 7 |
多列排序的话,传入一个 list of names:
frame.sort_values(by=['a', 'b'])
a | b | |
---|---|---|
2 | 0 | -3 |
0 | 0 | 4 |
3 | 1 | 2 |
1 | 1 | 7 |
ranking(排名)是给有效的数据分配数字。rank 方法能用于 series 和 DataFrame,rank 方法默认会给每个 group 一个 mean rank(平均排名)。rank 表示在这个数在原来的 Series 中排第几名,有相同的数,取其排名平均(默认)作为值:
obj = pd.Series([7, -5, 7, 4, 2, 0, 4]) obj
0 7 1 -5 2 7 3 4 4 2 5 0 6 4 dtype: int64
obj.sort_values()
1 -5 5 0 4 2 3 4 6 4 0 7 2 7 dtype: int64
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
在 obj 中,4 和 4 的排名是第 4 名和第五名,取平均得 4.5。7 和 7 的排名分别是第六名和第七名,则其排名取平均得 6.5。
rank 也可以根据数据被观测到的顺序来设定:
obj
0 7 1 -5 2 7 3 4 4 2 5 0 6 4 dtype: int64
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 dtype: float64
这里没有给 0 和 2(指两个数字 7)赋予 average rank 6.5,而是给第一个看到的 7(label 0)设置 rank 为 6,第二个看到的 7(label 2)设置 rank 为 7。
也可以设置降序:
# Assign tie values the maximum rank in the group obj.rank(ascending=False, method='max')
0 2.0 1 7.0 2 2.0 3 4.0 4 5.0 5 6.0 6 4.0 dtype: float64
dataframe 可以根据行或列来计算 rank:
frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1], 'c': [-2, 5, 8, -2.5]}) frame
a | b | c | |
---|---|---|---|
0 | 0 | 4.3 | -2.0 |
1 | 1 | 7.0 | 5.0 |
2 | 0 | -3.0 | 8.0 |
3 | 1 | 2.0 | -2.5 |
frame.rank(axis='columns') # columns 表示列与列之间的排序(即每一行里数据间的排序)
a | b | c | |
---|---|---|---|
0 | 2.0 | 3.0 | 1.0 |
1 | 1.0 | 3.0 | 2.0 |
2 | 2.0 | 1.0 | 3.0 |
3 | 2.0 | 3.0 | 1.0 |
8 Axis Indexes with Duplicate Labels (有重复 label 的轴索引)
我们看到的所有例子都有 unique axis labels(index values),唯一的轴标签(索引值)。一些 pandas 函数(reindex),需要 label 是唯一的,但这并是不强制的。比如下面有一个重复的索引:
obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c']) obj
a 0 a 1 b 2 b 3 c 4 dtype: int64
index 的 is_unique 特性能告诉我们 label 是否是唯一的:
obj.index.is_unique
False
数据选择对于重复 label 则表现有点不同。如果一个 label 有多个值,那么就会返回一个 series, 如果是 label 只对应一个值的话,会返回一个标量:
obj['a']
a 0 a 1 dtype: int64
obj['c']
4
这个选择的逻辑也应用于 DataFrame:
df = pd.DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b']) df
0 | 1 | 2 | |
---|---|---|---|
a | -0.314526 | -1.313861 | 0.823529 |
a | 0.994028 | -0.442338 | -0.846985 |
b | -1.340453 | -0.031612 | 0.044791 |
b | -0.919341 | -0.409164 | -1.297257 |
df.loc['b']
0 | 1 | 2 | |
---|---|---|---|
b | -1.340453 | -0.031612 | 0.044791 |
b | -0.919341 | -0.409164 | -1.297257 |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论