【基本工具】S02E08 DataFrame对象的数据选取方法

0.本集概览

1.对列标签进行字典形式的取值访问,获取Series对象
2.使用字典语法进行列的扩充
3.使用values属性,获取ndarray二维数组类型,可以使用相同操作方法
4.loc、iloc、ix三种索引器,支持行和列的索引、分片灵活操作
5.DataFrame的条件过滤操作
6.DataFrame具体值的修改

这一集,我们来说DataFrame对象的数据选取方法。同样,我们使用类比法进行学习,前面我们提到过,DataFrame可以看作是若干Series对象构成的字典,也可以看做是一个二维数组。

1.类比字典获取DataFrame指定数据

我们先类比字典,讨论如何获取DataFrame的指定数据,我们这一集例子中操作的就是下面这个DataFrame数据对象。
代码片段:

import pandas as pd

area = pd.Series({'California':423967,'Texas':695662,
                  'New York':141297,'Floriade':170312,
                  'Illinois':149995})

pop = pd.Series({'California':38332521,'Texas':26448193,
                  'New York':19651127,'Floriade':19552860,
                  'Illinois':12882135})

data = pd.DataFrame({'area':area, 'pop':pop})
print(data)

运行结果:

              area       pop
California  423967  38332521
Floriade    170312  19552860
Illinois    149995  12882135
New York    141297  19651127
Texas       695662  26448193

由于DataFrame本质上反映的是列标签与Series的映射关系,所以对列名进行字典形式的取值,可以获取相应的Series列数据
代码片段:

data = pd.DataFrame({'area':area, 'pop':pop})
print(data['area'])

运行结果:

California    423967
Floriade      170312
Illinois      149995
New York      141297
Texas         695662
Name: area, dtype: int64

和这种字典形式访问效果相同的是属性形式的访问方法,即data.area得到的结果和本例相同,不过属性访问方式的限制要多一些,例如如果列标签不是纯字符串或者恰巧与一些方法名重名,则不能使用该方法。

2.使用字典语法进行列扩充

当然,我们同样可以使用字典形式的语法进行列扩充,可以给一个新列赋值一个标量,也可以对其赋值一个向量数组:
代码片段:

data = pd.DataFrame({'area':area, 'pop':pop})
data['a'] = [1,2,3,4,5]
data['b'] = 0
print(data)

运行结果:

              area       pop  a  b
California  423967  38332521  1  0
Floriade    170312  19552860  2  0
Illinois    149995  12882135  3  0
New York    141297  19651127  4  0
Texas       695662  26448193  5  0

不过在日常使用中,某一列可能是其他两列通过算术运算得到的结果,例如,我们通过人口除以面积,可以得到每个州的人口密度,需要我们一个州一个州的循环计算吗?显然不需要,看看我们怎么做:
代码片段:

data = pd.DataFrame({'area':area, 'pop':pop})
data['density'] = data['pop'] / data['area']
print(data)

运行结果:

             area       pop     density
California  423967  38332521   90.413926
Floriade    170312  19552860  114.806121
Illinois    149995  12882135   85.883763
New York    141297  19651127  139.076746
Texas       695662  26448193   38.018740

3.类比ndarray获取数据

我们再看看,如果类比ndarray二维数组,我们如何处理DataFrame数据获取的需求。

首先我们可以用values属性,可以获得一个二维ndarray二维数组:
代码片段:

data = pd.DataFrame({'area':area, 'pop':pop})
data['density'] = data['pop'] / data['area']
print(data.values)

运行结果:

[[  4.23967000e+05   3.83325210e+07   9.04139261e+01]
 [  1.70312000e+05   1.95528600e+07   1.14806121e+02]
 [  1.49995000e+05   1.28821350e+07   8.58837628e+01]
 [  1.41297000e+05   1.96511270e+07   1.39076746e+02]
 [  6.95662000e+05   2.64481930e+07   3.80187404e+01]]

通过values属性可以获取二维ndarray数组形式的数据之后,我们自然可以像操作二维数组一样,对其进行行索引和值的索引。不过单独的列索引只能用刚刚讲过的传递列标签作为字典键的形式获取。
代码片段:

data = pd.DataFrame({'area':area, 'pop':pop})
data['density'] = data['pop'] / data['area']
print(data.values[2])
print(data.values[1][1])
print(data.values[1:][:2])

运行结果:

[  1.49995000e+05   1.28821350e+07   8.58837628e+01]

19552860.0

[[  1.70312000e+05   1.95528600e+07   1.14806121e+02]
 [  1.49995000e+05   1.28821350e+07   8.58837628e+01]]

自然而然我们会想,带有DataFrame本身标签结构的分片操作该如何进行,毕竟ndarray没有行、列信息,而这些信息恰是DataFrame的重要组成部分。

由于DataFrame的行和列的获取方法不太统一,所以DataFrame提供了三种索引器的方法,很好的满足了我们的需求。

4.三种索引器的行列索引方法

4.1.iloc索引

iloc索引,行列都使用隐式索引,我们可以像操作ndarray数组一样,对DataFrame数据类型进行索引分片操作:
代码片段:

data = pd.DataFrame({'area':area, 'pop':pop})
data['density'] = data['pop'] / data['area']
print(data.iloc[:2,1:2])

运行结果:

                 pop
California  38332521
Floriade    19552860

从这里我们可以看到,无论是行还是列,都采用隐式的整数索引进行分片,规则都是左闭右开。

4.2.loc索引

loc索引,则是采用显式的标签值索引进行分片,规则是左右都取:
代码片段:
```
import pandas as pd

area = pd.Series({'California':423967,'Texas':695662,
'New York':141297,'Floriade':170312,

top Created with Sketch.