访问元素和提取子集是数据框的基本操作,在pandas中,提供了多种方式。对于一个数据框而言,既有从0开始的整数下标索引,也有行列的标签索引
>>> df = pd.DataFrame(np.random.randn(4, 4), index=['r1', 'r2', 'r3', 'r4'], columns=['A', 'B', 'C', 'D'])>>> df
A B C D
r1 -0.220018 -0.398571 0.109313 0.186309
r2 -1.416611 0.826713 0.178174 0.117015
r3 -0.640207 -0.105941 -0.139368 -1.159992
r4 -2.254314 -1.228511 -2.080118 -0.212526
利用这两种索引,可以灵活的访问数据框中的元素,具体的操作方式有以下几种
1. 属性运算符
数据框的每一列是一个Series对象,属性操作符的本质是先根据列标签得到对应的Series对象,再根据Series对象的标签来访问其中的元素,用法如下
# 第一步,列标签作为属性,先得到Series对象>>> s = df.A
>>> s
r1 -0.220018
r2 -1.416611
r3 -0.640207
r4 -2.254314
Name: A, dtype: float64
# 第二步,在根据下标或者标签访问Series对象中的元素
>>> s.r1
-0.22001819046457136
>>> s[0]
-0.22001819046457136
# 属性操作符,一步法简写如下
>>> df.A.r1
-0.22001819046457136
属性操作符,一次只可以返回一个元素,适用于提取单列或者访问具体标量的操作。
2. 索引运算符
这里的索引运算符,有两种操作方式
列标签的用法,支持单个或者多个列标签,用法如下
# 单个列标签>>> df['A']
r1 -0.220018
r2 -1.416611
r3 -0.640207
r4 -2.254314
Name: A, dtype: float64
# 当然,你可以在列对应的Series对象中再次进行索引操作,访问对应元素
>>> df['A']['r1']
-0.22001819046457136
>>> df['A'][0]
-0.22001819046457136
# 多个列标签
>>> df[['A', 'B']]
A B
r1 -0.220018 -0.398571
r2 -1.416611 0.826713
r3 -0.640207 -0.105941
r4 -2.254314 -1.228511
对行进行切片的操作,用法如下
>>> df[:2]A B C D
r1 -0.220018 -0.398571 0.109313 0.186309
r2 -1.416611 0.826713 0.178174 0.117015
索引操作符,一次只能访问数据框的一个维度,适用于仅操作一个维度的场景。需要注意的是,当对不存在的列标签设值时,并不会报错,会自动进行append操作,示例如下
>>> df['E'] = 5>>> df
A B C D E
r1 0.706160 0.097334 0.241069 -0.412934 5
r2 -0.357353 1.053972 0.052277 -1.459352 5
r3 0.341270 0.551733 2.637333 0.494495 5
r4 1.506536 0.635737 1.083644 1.106261 5
另外,索引操作符支持布尔数组,本质是提取True对应的元素,本次示例如下
>>> df = pd.DataFrame(np.random.randn(4, 4), index=['r1', 'r2', 'r3', 'r4'], columns=['A', 'B', 'C', 'D'])>>> df
A B C D
r1 0.254875 0.627368 -1.488750 -1.134972
r2 -0.052981 -1.874639 -1.460659 1.020969
r3 -2.046727 1.460599 0.808164 -1.015956
r4 -0.385587 1.534610 -0.043623 -1.742118
>>> (df.A > df.B) & (df.B < df.C)
r1 False
r2 True
r3 False
r4 False
dtype: bool
>>> df[(df.A > df.B) & (df.B < df.C)]
A B C D
r2 -0.052981 -1.874639 -1.460659 1.020969
3. loc
loc功能灵活且强大,提供了基于标签的访问方式,先操作行标签,再操作列标签,用法如下
# 只提供一个标签,视为行标签>>> df.loc['r1']
A -0.220018
B -0.398571
C 0.109313
D 0.186309
Name: r1, dtype: float64
# 根据单个行列标签,访问对应元素
>>> df.loc['r1','A']
-0.22001819046457136
# 也支持多个行列标签,用列表的写法
>>> df.loc['r1', ['A', 'B']]
A -0.220018
B -0.398571
# :冒号是所有标签的简写
>>> df.loc[:,'A']
r1 -0.220018
r2 -1.416611
r3 -0.640207
r4 -2.254314
对于标签,支持切片操作,和python内置的切片规则不一样,loc的切片包含了终止点,用法如下
>>> df.loc['r1':'r3', 'A':'C']A B C
r1 -0.220018 -0.398571 0.109313
r2 -1.416611 0.826713 0.178174
r3 -0.640207 -0.105941 -0.139368
loc也支持布尔数组,本质是提取True对应的标签元素,用法如下
# 布尔数组# True对应的标签为C和D
>>> df.loc['r1'] > 0
A False
B False
C True
D True
Name: r1, dtype: bool
# 利用布尔数组,提取C,D两列
>>> df.loc[:, df.loc['r1'] > 0]
C D
r1 0.109313 0.186309
r2 0.178174 0.117015
r3 -0.139368 -1.159992
r4 -2.080118 -0.212526
# 最近构建布尔数组,来提取对应的行
>>> s = pd.Series([False, False, True, True], ['r1', 'r2', 'r3', 'r4'])
>>> s
r1 False
r2 False
r3 True
r4 True
dtype: bool
>>> df.loc[s, :]
A B C D
r3 -0.640207 -0.105941 -0.139368 -1.159992
r4 -2.254314 -1.228511 -2.080118 -0.212526
loc还支持函数调用,比如一个lambda匿名函数,用法如下
>>> df.loc[:, lambda df: ['A', 'B']]A B
r1 -0.220018 -0.398571
r2 -1.416611 0.826713
r3 -0.640207 -0.105941
r4 -2.254314 -1.228511
函数调用的本质是通过函数返回对应的标签,示例如下
>>> def extract_cols(df):... return(df.columns[0:2])
...
>>> extract_cols(df)
Index(['A', 'B'], dtype='object')
>>>
>>> df.loc[:, extract_cols]
A B
r1 -0.220018 -0.398571
r2 -1.416611 0.826713
r3 -0.640207 -0.105941
r4 -2.254314 -1.228511
在函数中,可以根据需要定义复杂的逻辑。需要注意的是,通过loc设置对应的值时,当key不存在时,会默认进行append操作,示例如下
# r5并不存在,但是不会报错>>> df.loc['r5'] = 1
# 自动追加了r5的内容
>>> df
A B C D
r1 -0.220018 -0.398571 0.109313 0.186309
r2 -1.416611 0.826713 0.178174 0.117015
r3 -0.640207 -0.105941 -0.139368 -1.159992
r4 -2.254314 -1.228511 -2.080118 -0.212526
r5 1.000000 1.000000 1.000000 1.000000
4. iloc
与loc相对应, iloc提供了基于下标索引访问元素的方式,用法和loc相同,只是将标签替换成了下标索引,示例如下
# 单个索引,视为行索引>>> df.iloc[0]
A -0.220018
B -0.398571
C 0.109313
D 0.186309
Name: r1, dtype: float64
# 单个行列索引
>>> df.iloc[0, 0]
-0.22001819046457136
# 多个行列索引
>>> df.iloc[[0, 1], [0, 1, 2]]
A B C
r1 -0.220018 -0.398571 0.109313
r2 -1.416611 0.826713 0.178174
# 索引切片
>>> df.iloc[:2, :2]
A B
r1 -0.220018 -0.398571
r2 -1.416611 0.826713
# 函数调用
>>> df.iloc[:, lambda df: [0, 1]]
A B
r1 -0.220018 -0.398571
r2 -1.416611 0.826713
r3 -0.640207 -0.105941
r4 -2.254314 -1.228511
5. at系列函数
上述几种方式都可以访问单个元素,但是由于考虑了很多的功能,其访问速度并不是最快的。针对访问单个元素的常见,pandas推荐使用at和iat函数,其中at使用标签进行访问,iat使用位置索引进行访问,用法如下
>>> df.at['r1', 'A']-0.22001819046457136
>>> df.iat[0, 0]
-0.22001819046457136
pandas中访问元素的具体方法还有很多,熟练使用行列标签,位置索引,布尔数组这三种基本的访问方式,就已经能够满足日常开发的需求了。
·end·
一个只分享干货的
生信公众号