Pandas超全总结

Pandas对象简介

可以把Pandas看成增强版的NumPy结构化数组,行列都不再只是简单的整数索引,还可以带上标签。Pandas有三个基本数据结构:Series、DataFrame、Index。

Series

Pandas的Series对象是一个带索引数据构成的一维数组。可以用一个数组创建Series对象:

>>> import numpy as np
>>> import pandas as pd
>>> data = pd.Series([0.25, 0.5, 0.75, 1.0])
>>> data
0    0.25
1    0.50
2    0.75
3    1.00
dtype: float64

从上面的结果中,你会发现Series对象将一组数据和一组索引绑定在一起,我们可以通过Values属性和index属性获取数据。values属性返回的结果与NumPy数组类似:

>>> data.values
array([0.25, 0.5 , 0.75, 1.  ])

index属性返回的结果是一个类型为pd.Index的类数组对象。

>>> data.index
RangeIndex(start=0, stop=4, step=1)

和NumPy数组一样,数据可以通过Python的中括号索引标签获取:

>>> data[1]
0.5
>>> data[1:3]
1    0.50
2    0.75
dtype: float64

1.Series是通用的NumPy数组

到目前为止,你可能觉得Series对象和一维NumPy数组基本可以等价交换,但两者的本质差异其实是索引:NumPy数组通过隐式定义的整数索引获取数值,而Pandas的Series对象用一种显示定义的索引与数值关联。
显示索引的定义让Series对象拥有了更强的能力。例如,索引不再仅仅是整数,还可以是任何想要的类型。如果需要,完全可以用字符串定义索引:

>>> data = pd.Series([0.25, 0.5, 0.75, 1.0], index=['a', 'b', 'c', 'd'])
>>> data
a    0.25
b    0.50
c    0.75
d    1.00
dtype: float64

也可以使用不连续的索引:

>>> data = pd.Series([0.25, 0.5, 0.75, 1.0], index=[2, 3, 5, 7])
>>> data
2    0.25
3    0.50
5    0.75
7    1.00
dtype: float64

2.Series是特殊的字典

你可以把Pandas的Series对象看成一种特殊的Python字典。字典是一种将任意键映射到一组任意值的数据结构,而Series对象其实是一种将类型键映射到一组类型值得数据结构。

>>> population_dict = {
   'California': 38332521,
					   'Texas': 26448193,
                       'New York': 19651127,
                       'Florida': 19552860,
                       'Illinois': 12882135}
>>> population = pd.Series(population_dict)
>>> population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
dtype: int64

和字典不同,Series对象还支持数组形式的操作,比如切片:

>>> population['California':'New York']
California    38332521
Texas         26448193
New York      19651127
dtype: int64

3.创建Series对象

我们已将见过几种创建Pandas的Series对象的方法,都是像这样的形式:

>>> pd.Series(data, index=index)

其中,index是一个可选参数,data参数支持各种数据类型。例如data可以是列表或者NumPy数组,这时index默认值为整数数列:

>>> pd.Series([2, 4, 6])
0    2
1    4
2    6
dtype: int64

data也可以是一个标量,创建Series对象会重复填充到每一个索引上:

>>> pd.Series(5)
0    5
dtype: int64
>>> pd.Series(5, index=[100, 200, 300])
100    5
200    5
300    5
dtype: int64

data还可以是一个字典:

>>> pd.Series({
   2:'a', 1:'b', 3:'c'})
2    a
1    b
3    c
dtype: object

DataFrame

和Series一样,DataFrame既可以作为一个通用性NumPy数组,也可以看做特殊的Python字典。

1.DataFrame是通用的NumPy数组

如果将Series类比作带灵活索引的一维数组,那么DataFrame就可以看做是一种既有灵活的行索引,又有灵活列索引的二维数组。

>>> population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
dtype: int64
>>> area_dict = {
   'California': 423967, 'Texas': 695662, 'New York': 141297,
'Florida': 170312, 'Illinois': 149995}
>>> area = pd.Series(area_dict)
>>> area
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
dtype: int64
>>> # 用一个字典创建一个包含这些信息的二维对象
>>> states = pd.DataFrame({
   'population':population, 'area':area})
>>> states
            population    area
California    38332521  423967
Texas         26448193  695662
New York      19651127  141297
Florida       19552860  170312
Illinois      12882135  149995

DataFrame的index属性和columns属性

>>> states.index
Index(['California', 'Texas', 'New York', 'Florida', 'Illinois'], dtype='object')
>>> states.columns
Index(['population', 'area'], dtype='object')

DataFrame可以看做一种通用的NumPy二维数组,它的行列都可以通过索引获取。

2.DataFrame是特殊字典

与Series类似,我们也可以把DataFrame看成一种特殊的字典。字典是一个键映射一个值,而DataFrame是一列映射一个Series的数据。

>>> states['area']
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64

需要注意的是,在NumPy的二维数组里,data[0]返回第一行;而在DataFrame中,data[‘col0’]返回第一列。

3.创建DataFrame对象

(1)通过单个Series对象创建。DataFrame是一组Series对象的集合,可以用单个Series创建一个单列的DataFrame:
>>> population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
dtype: int64
>>> pd.DataFrame(population, columns=['population'])
            population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
(2)通过字典列表创建。任何元素是字典的列表都可以变成DataFrame:
>>> data = [{
   'a':i, 'b':2 * i}for i in range(3)]
>>> data
[{
   'a': 0, 'b': 0}, {
   'a': 1, 'b': 2}, {
   'a': 2, 'b': 4}]
>>> pd.DataFrame(data)
   a  b
0  0  0
1  1  2
2  2  4

即使字典中有些键不在,Pandas也会用缺失值NaN(不是数字)来表示:

>>> pd.DataFrame([{
   'a':1, 'b':2},{
   'b':3, 'c':4}])
     a  b    c
0  1.0  2  NaN
1  NaN  3  4.0
(3)通过Series对象字典创建。就像之前见过的那样,DataFrame也可以用一个由Series对象构成的字典创建:
>>> pd.DataFrame({
   'population':population, 'area':area})
            population    area
California    38332521  423967
Texas         26448193  695662
New York      19651127  141297
Florida       19552860  170312
Illinois      12882135  149995
(4)通过NumPy二维数组创建。假如有一个二维数组,就可以创建一个可以指定行列索引值得DataFrame。如果不指定行列索引值,那么行列默认都是整数索引值:
pd.DataFrame(np.random.rand(3, 2), columns=['foo', 'bar'], index=['a', 'b', 'c'])
        foo       bar
a  0.086317  0.664006
b  0.582919  0.211217
c  0.341268  0.032053
(5)通过NumPy结构化数组创建

以后补充

数据取值与选择

Series数据选择方法

1.将Series看做字典

>>> data = pd.Series([0.25, 0.5, 0.75, 1.0], index=['a', 'b', 'c', 'd'])
>>> data
a    0.25
b    0.50
c    0.75
d    1.00
dtype: float64
>>> data['b']
0.5

我们还可以用Python字典的表达式和方法来检测键、索引和值:

>>> 'a' in data
True
>>> data.keys()
Index(['a', 'b', 'c', 'd'], dtype='object')
>>> list(data.items())
[('a', 0.25), ('b', 0.5), ('c', 0.75), ('d', 1.0)]
>>> data.values()
Traceback (most recent call last):
  File "<pyshell#82>", line 1, in <module>
    data.values()
TypeError: 'numpy.ndarray' object is not callable
>>> data.values
array([0.25, 0.5 , 0.75, 1.  ])

Series对象可以用字典语法调整数据,就像你可以通过增加新的键扩展字典一样,你也可以通过增加新的索引扩展Series:

>>> data['e'] = 1.25
>>> data
a    0.25
b    0.50
c    0.75
d    1.00
e    1.25
dtype: float64

2.将Series看做一维数组

Series不仅有着和字典一样的接口,而且还具备和NumPy数组一样的数组数据选择功能,包括索引、掩码、花俏的索引等操作:

>>> data
a    0.25
b    0.50
c    0.75
d    1.00
e    1.25
dtype: float64
>>> # 将显示索引作为切片
>>> data['a':'c']
a    0.25
b    0.50
c    0.75
dtype: float64
>>> # 将隐式索引作为切片
>>> data[0:2]
a    0.25
b    0.50
dtype: float64
>>> # 掩码
>>> data[(data > 0.3) & (data < 0.8)]
b    0.50
c    0.75
dtype: float64
>>> # 花俏的索引
>>> data[['a', 'e']]
a    0.25
e    1.25
dtype: float64

在以上所有示例中,切片是绝大部分混乱之源。需要注意的是,当使用显示索引(即data[‘a’:‘c’])做切片时,结果包含最后一个索引;而当使用隐式索引(即data[0:2])做切片时,结果不包含最后一个索引

3.索引器:loc、iloc和ix

这些切片和取值的习惯用法经常会造成混乱。例如,如果你的Series是显示整数索引,那么data[1]这样的取值操作会使用显式索引,而data[1:3]这样的切片操作却会使用隐式索引。

>>> data = pd.Series(['a', 'b', 'c'], index=[1, 3, 5])
>>> data
1    a
3    b
5    c
dtype: object
>>> # 取值操作是显式索引
>>> data[1]
'a'
>>> # 切片操作是隐式索引
>>> data[1:2]
3    b
dtype: object

由于整数索引很容易造成混淆,所以Pandas提供了一些索引器(indexer)属性来作为取值的方法。
第一种索引器是loc属性,表示取值和切片都是显示的:

>>> data
1    a
3    b
5    c
dtype: object
>>> data.loc[1]
'a'
>>> data.loc[1:3]
1    a
3    b
dtype: object

第二种是iloc属性,表示取值和切片都是Python形式的隐式索引:

>>> data
1    a
3    b
5    c
dtype: object
>>> data.iloc[1]
'b'
>>> data.iloc[1:3]
3    b
5    c
dtype: object

第三种取值属性是ix,它是前两种索引器的混合形式,之后会提到。
Python代码设计原则之一是“显式优于隐式”。使用loc和iloc可以让代码更容易维护,可读性更高。特别是在处理整数索引的对象时,我强烈推荐使用着两种索引器,它们既可以让代码阅读和理解起来更加容易,也能避免因误用索引/切片而产生的小bug。

DataFrame数据选择方法

1.将DataFrame看做字典

>>> area = pd.Series({
   'California': 423967, 'Texas': 695662, 'New York': 141297, 'Florida': 170312, 'Illinois': 149995})
>>> pop = pd.Series({
   'California': 38332521, 'Texas': 26448193, 'New York': 19651127, 'Florida': 19552860, 'Illinois': 12882135})
>>> data = pd.DataFrame({
   'area':area, 'pop':pop})
>>> data
              area       pop
California  423967  38332521
Texas       695662  26448193
New York    141297  19651127
Florida     170312  19552860
Illinois    149995  12882135

两个Series分别构成DataFrame的一列,可以通过对列名进行字典形式的取值来获取数据:

>>> data['area']
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64

对于字符串形式的列名,可以采用属性形式:

>>> data.area
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64

对同一个对象进行属性形式与字典形式获取的列数据,结果是相同的:

>>> data.area is data['area']
True

如果列名不是纯字符串,或者列名与DataFrame的方法同名,那么就不能用属性索引。
和Sries一样可以用字典形式的语法调整对象,比如增加一列:


>>> data['density'] = data['pop'] / data['area']
>>> data
              area       pop     density
California  423967  38332521   90.413926
Texas       695662  26448193   38.018740
New York    141297  19651127  139.076746
Florida     170312  19552860  114.806121
Illinois    149995  12882135   85.883763

2.将DataFrame看做二维数组

用values属性按行查看数组数据:

>>> data
              area       pop     density
California  423967  38332521   90.413926
Texas       695662  26448193   38.018740
New York    141297  19651127  139.076746
Florida     170312  19552860  114.806121
Illinois    149995  12882135   85.883763
>>> data.values
array([[4.23967000e+05, 3.83325210e+07, 9.04139261e+01],
       [6.95662000e+05, 2.64481930e+07, 3.80187404e+01],
       [1.41297000e+05, 1.96511270e+07, 1.39076746e+02],
       [1.70312000e+05, 1.95528600e+07, 1.14806121e+02],
       [1.49995000e+05, 1.28821350e+07, 8.58837628e+01]])

可以对DataFrame进行转置:

>>> data
              area       pop     density
California  423967  38332521   90.413926
Texas       695662  26448193   38.018740
New York    141297  19651127  139.076746
Florida     170312  19552860  114.806121
Illinois    149995  12882135   85.883763
>>> data.T
           California         Texas      New York       Florida      Illinois
area     4.239670e+05  6.956620e+05  1.412970e+05  1.703120e+05  1.499950e+05
pop      3.833252e+07  2.644819e+07  1.965113e+07  1.955286e+07  1.288214e+07
density  9.041393e+01  3.801874e+01  1.390767e+02  1.148061e+02  8.588376e+01

通过字典形式对列进行取值显然会限制我们把DataFrame作为NumPy数组可以获得的能力,尤其当我们在DataFrame数组中使用单个行索引获取一行数据时:

>>> data.values[0]
array([4.23967000e+05, 3.83325210e+07, 9.04139261e+01])
>>> # 而获取一列数据就需要向DataFrame传递单个列索引
>>> data['area']
California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64

因此,在进行数组形式的取值时,我们需要用另一种方法——前面介绍过的Pandas索引器loc、iloc和lx了。通过iloc索引器,我们可以像对待NumPy数组一样索引Pandas的底层数组,DataFrame的行列标签会自动保留在结果中:

>>> data
              area       pop     density
California  423967  38332521   90.413926
Texas       695662  26448193   38.018740
New York    141297  19651127  139.076746
Florida     170312  19552860  114.806121
Illinois    149995  12882135   85.883763
>>> data.iloc[:3, :2]
              area       pop
California  423967  38332521
Texas       695662  26448193
New York    141297  19651127
>>> data.loc[:'Illinois', :'pop']
              area       pop
California  423967  38332521
Texas       695662  26448193
New York    141297  19651127
Florida     170312  19552860
Illinois    149995  12882135

使用ix索引器可以实现一种混合效果:

>>> data.ix[:3, :'pop']
              area       pop
California  423967  38332521
Texas       695662  26448193
New York    141297  19651127

任何用于处理NumPy形式数据的方法都可以用于这些索引器。例如,在loc中结合使用掩码和花俏的索引方法:

>>> data.loc[data.density > 100, ['pop', 'density']]
               pop     density
New York  19651127  139.076746
Florida   19552860  114.806121

任何一种取值方法都可以用于调整数据,这一点和NumPy相同:

>>> data.iloc[0, 2] = 90
>>> data
              area       pop     density
California  423967  38332521   90.000000
Texas       695662  26448193   38.01874
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值