import pandas as pd
import numpy as np
概述
pandas 索引和选择的操作主要是以下五种:
操作 | 语法 | Result |
---|
选择列 | df[col] | Series |
通过标签选择行 | df.loc[label] | Series |
通过整数下标选择行 | df.iloc[loc] | Series |
行切片 | df[5:10] | DataFrame |
通过布尔向量切片 | df[bool_vec] | DataFrame |
df = pd.DataFrame(np.random.randn(4, 5), index=['a', 'b', 'c', 'd'], columns=['A', 'B', 'C', 'D', 'E'])
df
| A | B | C | D | E |
---|
a | -0.103212 | -0.719843 | -0.355287 | -0.440257 | 1.083105 |
---|
b | 1.215091 | 0.350809 | 1.129627 | 0.179248 | -0.367324 |
---|
c | 0.703286 | 0.733214 | -1.472511 | 1.311112 | -0.663189 |
---|
d | 0.644637 | 0.739376 | 1.270120 | -1.353912 | 0.187226 |
---|
a -0.719843
b 0.350809
c 0.733214
d 0.739376
Name: B, dtype: float64
| B | C |
---|
a | -0.719843 | -0.355287 |
---|
b | 0.350809 | 1.129627 |
---|
c | 0.733214 | -1.472511 |
---|
d | 0.739376 | 1.270120 |
---|
A 0.644637
B 0.739376
C 1.270120
D -1.353912
E 0.187226
Name: d, dtype: float64
A -0.103212
B -0.719843
C -0.355287
D -0.440257
E 1.083105
Name: a, dtype: float64
| A | B | C | D | E |
---|
a | -0.103212 | -0.719843 | -0.355287 | -0.440257 | 1.083105 |
---|
b | 1.215091 | 0.350809 | 1.129627 | 0.179248 | -0.367324 |
---|
c | 0.703286 | 0.733214 | -1.472511 | 1.311112 | -0.663189 |
---|
| A | B | C | D | E |
---|
a | False | False | False | False | True |
---|
b | True | True | True | True | False |
---|
| A | B | C | D | E |
---|
a | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.083105 |
---|
b | 1.215091 | 0.350809 | 1.129627 | 0.179248 | 0.000000 |
---|
c | 0.703286 | 0.733214 | 0.000000 | 1.311112 | 0.000000 |
---|
d | 0.644637 | 0.739376 | 1.270120 | 0.000000 | 0.187226 |
---|
使用 [] 进行索引
使用 []
进行索引,实际上就是选择低维切片。对于 Series 对象和 DataFrame 对象,[]
返回的类型不同。
对象类型 | 调用方法 | 返回值类型 |
---|
Series | series[label] | 标量值 |
DataFrame | frame[colname] | 对应 colname 的 Series |
dates = pd.date_range('1/1/2000', periods=8)
df = pd.DataFrame(np.random.randn(8, 4),
index=dates, columns=['A', 'B', 'C', 'D'])
df
| A | B | C | D |
---|
2000-01-01 | 0.169225 | -0.158166 | -0.166857 | -0.078189 |
---|
2000-01-02 | 0.584719 | 0.631690 | 0.001675 | 0.263198 |
---|
2000-01-03 | -0.234786 | -1.622012 | -0.705652 | -0.171561 |
---|
2000-01-04 | 1.038103 | -1.316517 | -0.135135 | -0.411320 |
---|
2000-01-05 | 1.123070 | 0.290033 | -0.372262 | -0.340214 |
---|
2000-01-06 | 0.900263 | 0.304163 | -1.663322 | 0.633026 |
---|
2000-01-07 | 0.766208 | 0.359713 | -0.460340 | 0.746346 |
---|
2000-01-08 | 0.864615 | -0.576092 | 0.065375 | -1.200949 |
---|
2000-01-01 0.169225
2000-01-02 0.584719
2000-01-03 -0.234786
2000-01-04 1.038103
2000-01-05 1.123070
2000-01-06 0.900263
2000-01-07 0.766208
2000-01-08 0.864615
Freq: D, Name: A, dtype: float64
0.9002627651374207
交换 A
和 B
两列:
df[['B', 'A']] = df[['A', 'B']]
df
| A | B | C | D |
---|
2000-01-01 | -0.158166 | 0.169225 | -0.166857 | -0.078189 |
---|
2000-01-02 | 0.631690 | 0.584719 | 0.001675 | 0.263198 |
---|
2000-01-03 | -1.622012 | -0.234786 | -0.705652 | -0.171561 |
---|
2000-01-04 | -1.316517 | 1.038103 | -0.135135 | -0.411320 |
---|
2000-01-05 | 0.290033 | 1.123070 | -0.372262 | -0.340214 |
---|
2000-01-06 | 0.304163 | 0.900263 | -1.663322 | 0.633026 |
---|
2000-01-07 | 0.359713 | 0.766208 | -0.460340 | 0.746346 |
---|
2000-01-08 | -0.576092 | 0.864615 | 0.065375 | -1.200949 |
---|
注意,如果使用了 loc
或者 iloc
,pandas 会先对齐所有 axes
。这不会修改 df
,因为列对齐在赋值之前。
df.loc[:, ['B', 'A']] = df[['A', 'B']]
df
| A | B | C | D |
---|
2000-01-01 | -0.158166 | 0.169225 | -0.166857 | -0.078189 |
---|
2000-01-02 | 0.631690 | 0.584719 | 0.001675 | 0.263198 |
---|
2000-01-03 | -1.622012 | -0.234786 | -0.705652 | -0.171561 |
---|
2000-01-04 | -1.316517 | 1.038103 | -0.135135 | -0.411320 |
---|
2000-01-05 | 0.290033 | 1.123070 | -0.372262 | -0.340214 |
---|
2000-01-06 | 0.304163 | 0.900263 | -1.663322 | 0.633026 |
---|
2000-01-07 | 0.359713 | 0.766208 | -0.460340 | 0.746346 |
---|
2000-01-08 | -0.576092 | 0.864615 | 0.065375 | -1.200949 |
---|
可以强转成 ndarray
数组来实现这一操作:
df.loc[:, ['B', 'A']] = df[['A', 'B']].to_numpy()
df
| A | B | C | D |
---|
2000-01-01 | 0.169225 | -0.158166 | -0.166857 | -0.078189 |
---|
2000-01-02 | 0.584719 | 0.631690 | 0.001675 | 0.263198 |
---|
2000-01-03 | -0.234786 | -1.622012 | -0.705652 | -0.171561 |
---|
2000-01-04 | 1.038103 | -1.316517 | -0.135135 | -0.411320 |
---|
2000-01-05 | 1.123070 | 0.290033 | -0.372262 | -0.340214 |
---|
2000-01-06 | 0.900263 | 0.304163 | -1.663322 | 0.633026 |
---|
2000-01-07 | 0.766208 | 0.359713 | -0.460340 | 0.746346 |
---|
2000-01-08 | 0.864615 | -0.576092 | 0.065375 | -1.200949 |
---|
切片
切片的规则和 Python 以及 NumPy 中的切片规则,一样。这里用 []
运算符说明切片的语义。
s = pd.Series(np.random.randn(7), index=list('abcdefg'))
s
a -0.381270
b -0.485434
c -0.298939
d 0.508133
e 0.961189
f 0.107214
g -1.452212
dtype: float64
a -0.381270
b -0.485434
c -0.298939
d 0.508133
e 0.961189
dtype: float64
a -0.381270
c -0.298939
e 0.961189
g -1.452212
dtype: float64
g -1.452212
f 0.107214
e 0.961189
d 0.508133
c -0.298939
b -0.485434
a -0.381270
dtype: float64
a 0.000000
b 0.000000
c 0.000000
d 0.508133
e 0.961189
f 0.107214
g -1.452212
dtype: float64
df = pd.DataFrame(np.random.randn(3, 4), index=list('abc'), columns=list('ABCD'))
df
| A | B | C | D |
---|
a | 0.871967 | 1.381672 | 0.395105 | -1.459083 |
---|
b | 1.466618 | 1.626593 | -1.002821 | 0.092995 |
---|
c | 0.384346 | 0.020456 | -0.441192 | -0.476958 |
---|
| A | B | C | D |
---|
a | 0.871967 | 1.381672 | 0.395105 | -1.459083 |
---|
b | 1.466618 | 1.626593 | -1.002821 | 0.092995 |
---|
| A | B | C | D |
---|
c | 0.384346 | 0.020456 | -0.441192 | -0.476958 |
---|
b | 1.466618 | 1.626593 | -1.002821 | 0.092995 |
---|
a | 0.871967 | 1.381672 | 0.395105 | -1.459083 |
---|
通过属性索引
s = pd.Series([1, 2, 3], index=list('abc'))
s
a 1
b 2
c 3
dtype: int64
2
df = pd.DataFrame(np.random.randn(3, 4), index=list('abc'), columns=list('ABCD'))
df
| A | B | C | D |
---|
a | 0.147620 | -1.336105 | 0.945316 | 0.501963 |
---|
b | 1.220405 | 0.697981 | -0.869925 | 0.790545 |
---|
c | 0.935809 | 0.584775 | 1.316057 | 0.138111 |
---|
a 0.147620
b 1.220405
c 0.935809
Name: A, dtype: float64
df.A = list(range(len(df.index)))
df
| A | B | C | D |
---|
a | 0 | -1.336105 | 0.945316 | 0.501963 |
---|
b | 1 | 0.697981 | -0.869925 | 0.790545 |
---|
c | 2 | 0.584775 | 1.316057 | 0.138111 |
---|
采用访问属性的方法必须确保该属性存在。如果要创建新的一列,仍然需要通过 []
。否则,会出现 UserWanring
的警告。
df['E'] = list(range(len(df.index)))
df
| A | B | C | D | E |
---|
a | 0 | -1.336105 | 0.945316 | 0.501963 | 0 |
---|
b | 1 | 0.697981 | -0.869925 | 0.790545 | 1 |
---|
c | 2 | 0.584775 | 1.316057 | 0.138111 | 2 |
---|
通过标签索引
使用 loc
方法可以使用标签对行进行索引。
s = pd.Series(np.random.randn(6), index=list('abcdef'))
s
a 0.763607
b -0.538096
c -0.032027
d 0.312734
e 1.096504
f -0.857242
dtype: float64
-0.5380958810076775
标签支持冒号表达式,进行切片运算。
c -0.032027
d 0.312734
e 1.096504
f -0.857242
dtype: float64
df = pd.DataFrame(np.random.randn(6, 4), index=list('abcdef'), columns=list('ABCD'))
df
| A | B | C | D |
---|
a | -0.367401 | 2.027401 | -0.379841 | -1.462746 |
---|
b | 0.032665 | 0.143619 | -2.085444 | 0.442935 |
---|
c | -1.117230 | 0.937448 | 0.738852 | -0.411036 |
---|
d | 0.238427 | 0.326619 | 0.182713 | 1.151853 |
---|
e | 0.454272 | 0.844479 | -1.220454 | -1.453612 |
---|
f | -1.706529 | -0.733242 | 0.400927 | -0.431352 |
---|
DataFrame 对象可以行列同时索引。
df.loc[['a', 'b', 'd'], ['A', 'C']]
| A | C |
---|
a | -0.367401 | -0.379841 |
---|
b | 0.032665 | -2.085444 |
---|
d | 0.238427 | 0.182713 |
---|
| A | B | C |
---|
d | 0.238427 | 0.326619 | 0.182713 |
---|
e | 0.454272 | 0.844479 | -1.220454 |
---|
f | -1.706529 | -0.733242 | 0.400927 |
---|
注意:下面的切片不是下标切片,而是标签切片。因此,3:5
表示标签 3
和 5
之间的所有标签。3
和 5
之间还有一个标签 2
,因此返回结果为:
s = pd.Series(list('abcdef'), index=[0, 3, 2, 5, 4, 2])
s.loc[3:5]
3 b
2 c
5 d
dtype: object
通过下标位置索引
使用 iloc
方法可以通过下标位置进行索引。
s = pd.Series(np.random.randn(5), index=list(range(0, 10, 2)))
s
0 -0.465348
2 -0.507533
4 0.600791
6 -0.485520
8 0.703295
dtype: float64
0 -0.465348
2 -0.507533
4 0.600791
dtype: float64
0.7032949052125851
df = pd.DataFrame(np.random.randn(6, 4),
index=list(range(0, 12, 2)),
columns=list(range(0, 8, 2)))
df
| 0 | 2 | 4 | 6 |
---|
0 | 1.490701 | -0.549809 | 0.504431 | -1.027572 |
---|
2 | -1.790752 | 0.687135 | 0.674383 | -1.053664 |
---|
4 | 1.168693 | -0.129001 | 0.078535 | -0.770111 |
---|
6 | 0.711808 | -0.269357 | 1.663142 | -1.358983 |
---|
8 | -0.405399 | -0.868119 | 0.183488 | -1.307719 |
---|
10 | 2.091057 | 0.426331 | 0.120099 | 0.599744 |
---|
DataFrame 对象可以行列同时索引。
| 0 | 2 | 4 | 6 |
---|
0 | 1.490701 | -0.549809 | 0.504431 | -1.027572 |
---|
2 | -1.790752 | 0.687135 | 0.674383 | -1.053664 |
---|
4 | 1.168693 | -0.129001 | 0.078535 | -0.770111 |
---|
| 4 | 6 |
---|
2 | 0.674383 | -1.053664 |
---|
4 | 0.078535 | -0.770111 |
---|
6 | 1.663142 | -1.358983 |
---|
8 | 0.183488 | -1.307719 |
---|
df.iloc[[1, 3, 5], [1, 3]]
| 2 | 6 |
---|
2 | 0.687135 | -1.053664 |
---|
6 | -0.269357 | -1.358983 |
---|
10 | 0.426331 | 0.599744 |
---|
| 0 | 2 | 4 | 6 |
---|
2 | -1.790752 | 0.687135 | 0.674383 | -1.053664 |
---|
4 | 1.168693 | -0.129001 | 0.078535 | -0.770111 |
---|
可以超出索引范围,但是可能会返回空 DataFrame。
选择接受可调用对象
[]
、loc
和 iloc
都接受可调用对象进行索引。
df = pd.DataFrame(np.random.randn(6, 4),
index=list('abcdef'),
columns=list('ABCD'))
df
| A | B | C | D |
---|
a | -0.363806 | 2.135196 | 0.112095 | 0.183855 |
---|
b | 0.964061 | 1.549231 | 0.162025 | 1.408502 |
---|
c | 0.033714 | 0.484294 | 0.895077 | 1.834204 |
---|
d | -1.632735 | 0.628079 | 1.497278 | 1.194587 |
---|
e | -1.692414 | 0.494285 | 1.618099 | -1.882802 |
---|
f | -1.543841 | 0.550801 | -1.429393 | -0.001107 |
---|
df.loc[lambda df: df['A'] > 0, :]
| A | B | C | D |
---|
b | 0.964061 | 1.549231 | 0.162025 | 1.408502 |
---|
c | 0.033714 | 0.484294 | 0.895077 | 1.834204 |
---|
df.loc[:, lambda df: ['A', 'B']]
| A | B |
---|
a | -0.363806 | 2.135196 |
---|
b | 0.964061 | 1.549231 |
---|
c | 0.033714 | 0.484294 |
---|
d | -1.632735 | 0.628079 |
---|
e | -1.692414 | 0.494285 |
---|
f | -1.543841 | 0.550801 |
---|
df.iloc[:, lambda df: [0, 1]]
| A | B |
---|
a | -0.363806 | 2.135196 |
---|
b | 0.964061 | 1.549231 |
---|
c | 0.033714 | 0.484294 |
---|
d | -1.632735 | 0.628079 |
---|
e | -1.692414 | 0.494285 |
---|
f | -1.543841 | 0.550801 |
---|
df[lambda df: df.columns[0]]
a -0.363806
b 0.964061
c 0.033714
d -1.632735
e -1.692414
f -1.543841
Name: A, dtype: float64
df['A'].loc[lambda s: s > 0]
b 0.964061
c 0.033714
Name: A, dtype: float64
快速访问
由于使用 []
进行索引必须处理很多情况(单标签访问、切片、布尔索引等),因此它需要一些开销才能确定您的要求。如果您只想访问一个标量值,最快的方法是使用 at
和 iat
方法,它们在所有数据结构上都实现了。
s = pd.Series(np.random.randint(0, 7, size=(7,)), index=list('abcdefg'))
s
a 0
b 6
c 0
d 6
e 6
f 1
g 1
dtype: int32
1
0
df = pd.DataFrame(np.random.randint(0, 7, size=(3, 4)), index=list('abc'), columns=list('ABCD'))
df
5
1
布尔索引
Series 对象的布尔索引和 Python 以及 NumPy 类似。
s = pd.Series(range(-3, 4))
s
0 -3
1 -2
2 -1
3 0
4 1
5 2
6 3
dtype: int64
4 1
5 2
6 3
dtype: int64
0 -3
1 -2
4 1
5 2
6 3
dtype: int64
3 0
4 1
5 2
6 3
dtype: int64
df = pd.DataFrame(np.random.randn(7, 4),
index=pd.date_range('2022/02/22', periods=7),
columns=list('ABCD'))
df
| A | B | C | D |
---|
2022-02-22 | -1.645831 | -0.603577 | 0.855909 | -0.172192 |
---|
2022-02-23 | -0.006510 | -0.708135 | -0.788163 | -2.029753 |
---|
2022-02-24 | -1.034041 | 0.977184 | -0.176987 | -0.066881 |
---|
2022-02-25 | 0.713977 | 2.029726 | -0.441814 | 0.105782 |
---|
2022-02-26 | -0.038251 | -1.624340 | -0.882659 | 0.655924 |
---|
2022-02-27 | 1.122102 | -0.019443 | 1.120410 | -0.599446 |
---|
2022-02-28 | 1.829295 | 0.039461 | -0.468706 | 1.038191 |
---|
| A | B | C | D |
---|
2022-02-25 | 0.713977 | 2.029726 | -0.441814 | 0.105782 |
---|
2022-02-27 | 1.122102 | -0.019443 | 1.120410 | -0.599446 |
---|
2022-02-28 | 1.829295 | 0.039461 | -0.468706 | 1.038191 |
---|
高级布尔函数
isin(values)
用于判断元素是否包含在 values
中,适用于 Series
,DataFrame
和 Index
对象。
df = pd.DataFrame({'num_legs': [2, 4], 'num_wings': [2, 0]},
index=['falcon', 'dog'])
df
| num_legs | num_wings |
---|
falcon | 2 | 2 |
---|
dog | 4 | 0 |
---|
isin
函数可以接受 list、dict、Seires 等可迭代对象作为参数。
| num_legs | num_wings |
---|
falcon | True | True |
---|
dog | False | True |
---|
如果传入的是 dict,则可以分别设置每一列的判断规则。如若不设置,默认得到 False。
df.isin({'num_wings': [0, 3]})
| num_legs | num_wings |
---|
falcon | False | False |
---|
dog | False | True |
---|
如果传入的是 Series 或者 DataFrame 对象,那么必须确保每行每列匹配。
other = pd.DataFrame({'num_legs': [8, 3], 'num_wings': [0, 2]},
index=['spider', 'falcon'])
df.isin(other)
| num_legs | num_wings |
---|
falcon | False | True |
---|
dog | False | False |
---|
查询 num_wings
列中值为 2 或 4 的行。
df[df["num_wings"].isin([2, 4])]
| num_legs | num_wings |
---|
falcon | 2 | 2 |
---|
过滤并保留 num_wings
列中值为 4 或 8 的行。
df = df[df["num_legs"].isin([4, 8])]
df