Advertisement

pandas教程:Introduction to pandas Data Structures pandas的数据结构

阅读量:

pandas是Python中用于数据分析和操作的库,其核心数据结构包括Series和DataFrame。Series是pandas中类似于数组的一维数据结构,具有索引(index)和标签(label)的特性。通过pd.Series()可以创建Series,其索引可以是字符串或其他类型。例如:
python obj = pd.Series([4, 7, -5, 3]) obj 0 4 1 7 2 -5 3 3 dtype: int64
DataFrame是pandas中二维数据结构,类似于Excel表格。可以通过字典或列表构建DataFrame,并支持行和列的索引操作。例如:
python data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002, 2003], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]} frame = pd.DataFrame(data) frame
DataFrame支持数据对齐操作,类似Excel的合并功能。可以通过loc属性按行或列标签进行定位。例如:
python frame.loc['three']
pandas的Index对象负责存储轴标签,支持不可变操作,如选择子集或转置。例如:
python frame3 = pd.DataFrame(pop, index=[2001, 2002, 2003]) frame3.T
通过pd.Index()可以创建自定义索引,支持集合操作。例如:
python labels = pd.Index(np.arange(3)) labels
pandas提供了丰富的方法和属性,如values获取二维数组,isnull检测缺失值等。例如:
python frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'], index=['one', 'two', 'three', 'four', 'five', 'six']) frame2['debt'] = np.arange(6.) frame2
通过这些操作,pandas为数据分析提供了强大的工具支持。

文章目录

  • 第5章 初识pandas
    • 5.1 探索pandas数据结构
      1. Series对象
      1. DataFrame对象
      1. 索引对象

Chapter 5 Getting Started with pandas

这样导入pandas

复制代码
    import pandas as pd
复制代码
    e:\python3.7\lib\site-packages\numpy\_distributor_init.py:32: UserWarning: loaded more than 1 DLL from .libs:
    e:\python3.7\lib\site-packages\numpy\.libs\libopenblas.TXA6YQSD3GCQQC22GEQ54J2UDCXDXHWN.gfortran-win_amd64.dll
    e:\python3.7\lib\site-packages\numpy\.libs\libopenblas.XWYDX2IKJW2NMTWSFYNGFUWKQU3LYTCZ.gfortran-win_amd64.dll
      stacklevel=1)

另外可以导入SeriesDataFrame,因为这两个经常被用到:

复制代码
    from pandas import Series, DataFrame

5.1 Introduction to pandas Data Structures

在数据结构领域中,该课程的核心内容具体来说,涉及SeriesDataFrame这两个核心概念。

1 Series

这里series这个词我就不翻译成序列了,因为之前的所有笔记里,我都是把sequence这个词翻译成序列的。

series类似于数组的一种一维序列,同时它还伴随着一个用于表示label的数组,这个数组被称为index。构建一个series的过程相对直接:

复制代码
    obj = pd.Series([4, 7, -5, 3])
    obj
复制代码
    0    4
    1    7
    2   -5
    3    3
    dtype: int64

观察到左边标记了index,右边标注了对应的value。通过valueindex属性,可以轻松地进行查看。

复制代码
    obj.values
复制代码
    array([ 4,  7, -5,  3], dtype=int64)
复制代码
    obj.index # like range(4)
复制代码
    RangeIndex(start=0, stop=4, step=1)

当然我们也可以自己指定indexlabel

复制代码
    obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])
复制代码
    obj2
复制代码
    d    4
    b    7
    a   -5
    c    3
    dtype: int64
复制代码
    obj2.index
复制代码
    Index(['d', 'b', 'a', 'c'], dtype='object')

可以用indexlabel来选择:

复制代码
    obj2['a']
复制代码
    -5
复制代码
    obj2['d'] = 6
复制代码
    obj2[['c', 'a', 'd']]
复制代码
    c    3
    a   -5
    d    6
    dtype: int64

这里[‘c’, ‘a’, ‘d’]其实被当做了索引,尽管这个索引是用string构成的。

使用numpy函数或类似的操作,会保留index-value的关系:

复制代码
    obj2[obj2 > 0]
复制代码
    d    6
    b    7
    c    3
    dtype: int64
复制代码
    obj2
复制代码
    d    12
    b    14
    a   -10
    c     6
    dtype: int64
复制代码
    import numpy as np
    np.exp(obj2)
复制代码
    d     403.428793
    b    1096.633158
    a       0.006738
    c      20.085537
    dtype: float64

另一种方式来看待series,它相当于一个固定长度、有序的dict,从indexvalue进行映射。在多个场景中,可以将其视为dict来使用。

复制代码
    'b' in obj2
复制代码
    True
复制代码
    'e' in obj2
复制代码
    False

还可以直接用现有的dict来创建series

复制代码
    sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon':16000, 'Utah': 5000}
复制代码
    obj3 = pd.Series(sdata)
    obj3
复制代码
    Ohio      35000
    Texas     71000
    Oregon    16000
    Utah       5000
    dtype: int64

series中的index本质上是dict中有序排列的keys。我们还可以指定一个自定义的排序顺序:

复制代码
    states = ['California', 'Ohio', 'Oregon', 'Texas']
复制代码
    obj4 = pd.Series(sdata, index=states)
    obj4
复制代码
    California        NaN
    Ohio          35000.0
    Oregon        16000.0
    Texas         71000.0
    dtype: float64

顺序是遵循states中的排列,但因未找到california,即为NaNNaN代表缺失数据,即在提到时,我们用missingNA来指代。pandas中,isnullnotnull函数可用于识别缺失数据:

复制代码
    pd.isnull(obj4)
复制代码
    California     True
    Ohio          False
    Oregon        False
    Texas         False
    dtype: bool
复制代码
    pd.notnull(obj4)
复制代码
    California    False
    Ohio           True
    Oregon         True
    Texas          True
    dtype: bool

series也有对应的方法:

复制代码
    obj4.isnull()
复制代码
    California     True
    Ohio          False
    Oregon        False
    Texas         False
    dtype: bool

关于缺失数据,在第七章还会讲得更详细一些。

series中,一个有实用价值的特性会根据index label进行排序(Data alignment features

复制代码
    obj3
复制代码
    Ohio      35000
    Texas     71000
    Oregon    16000
    Utah       5000
    dtype: int64
复制代码
    obj4
复制代码
    California        NaN
    Ohio          35000.0
    Oregon        16000.0
    Texas         71000.0
    dtype: float64
复制代码
    obj3 + obj4
复制代码
    California         NaN
    Ohio           70000.0
    Oregon         32000.0
    Texas         142000.0
    Utah               NaN
    dtype: float64

这个Data alignment features(数据对齐特色)和数据库中的join相似。

series自身属性和其index都具有名为name的属性,该属性能够与其他pandas函数进行整合:

复制代码
    obj4.name = 'population'
复制代码
    obj4.index.name = 'state'
复制代码
    obj4
复制代码
    state
    California        NaN
    Ohio          35000.0
    Oregon        16000.0
    Texas         71000.0
    Name: population, dtype: float64

seriesindex能被直接更改:

复制代码
    obj
复制代码
    0    4
    1    7
    2   -5
    3    3
    dtype: int64
复制代码
    obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
    obj
复制代码
    Bob      4
    Steve    7
    Jeff    -5
    Ryan     3
    dtype: int64

2 DataFrame

DataFrame是一种二维表格结构,代表一种排好序的列集合,其中每一列可以是不同类型的数值数据(如数字、字符串、布尔值)。DataFrame包含行索引和列索引(row index, column index),可以理解为一种共享所有索引的由series组成的字典结构。数据以多维块存储结构保存。

我将dataframe视为类似于Excel表格的存在,这样使用起来更加直观。

构建一个dataframe的方法,用一个dcitdict里的值是list

复制代码
    data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'], 
        'year': [2000, 2001, 2002, 2001, 2002, 2003], 
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
    
    frame = pd.DataFrame(data)
    
    frame
pop state year
0 1.5 Ohio 2000
1 1.7 Ohio 2001
2 3.6 Ohio 2002
3 2.4 Nevada 2001
4 2.9 Nevada 2002
5 3.2 Nevada 2003

dataframe也会像series一样,自动给数据赋index, 而列则会按顺序排好。

对于一个较大的DataFrame,通过head方法调用可以获取前五行数据(注:在数据分析中,该函数常被用来查看数据集的前几行内容,帮助了解数据结构)

复制代码
    frame.head()
pop state year
0 1.5 Ohio 2000
1 1.7 Ohio 2001
2 3.6 Ohio 2002
3 2.4 Nevada 2001
4 2.9 Nevada 2002

如果指定一列的话,会自动按列排序:

复制代码
    pd.DataFrame(data, columns=['year', 'state', 'pop'])
year state pop
0 2000 Ohio 1.5
1 2001 Ohio 1.7
2 2002 Ohio 3.6
3 2001 Nevada 2.4
4 2002 Nevada 2.9
5 2003 Nevada 3.2

如果你导入一个不存在的列名,那么会显示为缺失数据:

复制代码
    frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'], 
                      index=['one', 'two', 'three', 'four', 'five', 'six'])
复制代码
    frame2
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 NaN
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 NaN
five 2002 Nevada 2.9 NaN
six 2003 Nevada 3.2 NaN
复制代码
    frame2.columns
复制代码
    Index(['year', 'state', 'pop', 'debt'], dtype='object')

DataFrame中提取一列会返回series类型的数据,也可以以属性或字典形式提取数据:

复制代码
    frame2['state']
复制代码
    one        Ohio
    two        Ohio
    three      Ohio
    four     Nevada
    five     Nevada
    six      Nevada
    Name: state, dtype: object
复制代码
    frame2.year
复制代码
    one      2000
    two      2001
    three    2002
    four     2001
    five     2002
    six      2003
    Name: year, dtype: int64

提示:通过frame2[column]结构,可以处理任意列名,但仅当frame2.column时,column必须是合法的Python变量名。

返回的seriesDataFrame种同样的index,而且name属性也是对应的。

对于行,要用在loc属性里用 位置或名字:

复制代码
    frame2.loc['three']
复制代码
    year     2002
    state    Ohio
    pop       3.6
    debt      NaN
    Name: three, dtype: object

列值也能通过赋值改变。比如给debt赋值:

复制代码
    frame2['debt'] = 16.5
    frame2
year state pop debt
one 2000 Ohio 1.5 16.5
two 2001 Ohio 1.7 16.5
three 2002 Ohio 3.6 16.5
four 2001 Nevada 2.4 16.5
five 2002 Nevada 2.9 16.5
six 2003 Nevada 3.2 16.5
复制代码
    frame2['debt'] = np.arange(6.)
    frame2
year state pop debt
one 2000 Ohio 1.5 0.0
two 2001 Ohio 1.7 1.0
three 2002 Ohio 3.6 2.0
four 2001 Nevada 2.4 3.0
five 2002 Nevada 2.9 4.0
six 2003 Nevada 3.2 5.0

在将listarray赋值给column时,必须确保其长度与DataFrame的行数一致。相反,若将series赋值给DataFrame,系统会根据DataFrame的索引进行对齐,若series长度不足,缺失值将被填充。

复制代码
    val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
    frame2['debt'] = val
    frame2
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 -1.2
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 -1.5
five 2002 Nevada 2.9 -1.7
six 2003 Nevada 3.2 NaN

若列不存在,赋值操作会生成一个新列。同样地,使用del进行删除操作,其行为类似于删除字典键的行为。

复制代码
    frame2['eastern'] = frame2.state == 'Ohio'
    frame2
year state pop debt eastern
one 2000 Ohio 1.5 NaN True
two 2001 Ohio 1.7 -1.2 True
three 2002 Ohio 3.6 NaN True
four 2001 Nevada 2.4 -1.5 False
five 2002 Nevada 2.9 -1.7 False
six 2003 Nevada 3.2 NaN False

然后用del删除这一列:

复制代码
    del frame2['eastern']
复制代码
    frame2.columns
复制代码
    Index(['year', 'state', 'pop', 'debt'], dtype='object')

注意:columns返回的是一个view,而不是创建了一个copied object。因此,任何对series的修改,会作用于整个DataFrame。除非我们使用copy方法来创建一个新的副本。

另一种常见的格式是dict中的dict

复制代码
    pop = {'Nevada': {2001: 2.4, 2002: 2.9},
       'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

将这种嵌入式字典传递给DataFrame,pandas会将外层dict的键作为列,内层键作为索引:

当嵌入式字典被传递给DataFrame时,pandas会将外层dict的键作为列,内层键作为索引:

将嵌入式dict传递给DataFrame,pandas会将外层dict的键作为列,内层键作为行索引:

当嵌套字典传递给DataFrame时,pandas会将外层字典的键作为列,内层键作为索引:

将嵌套dict传递给DataFrame,pandas会将外层dict的键作为列,内层键作为行索引:

当嵌入式字典被传递给DataFrame时,pandas会将外层字典的键作为列,内层键作为索引:

将嵌入式dict传递给DataFrame,pandas会将外层dict的键作为列,内层键作为索引:

当嵌入式字典被传递给DataFrame时,pandas会将外层dict的键作为列,内层键作为索引:

将嵌入式dict传递给DataFrame,pandas会将外层dict的键作为列,内层键作为索引:

当嵌入式字典被传递给DataFrame时,pandas会将外层dict的键作为列,内层键作为索引:

复制代码
    frame3 = pd.DataFrame(pop)
    frame3
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6

另外DataFrame也可以向numpy数组一样做转置:

复制代码
    frame3.T
2000 2001 2002
Nevada NaN 2.4 2.9
Ohio 1.5 1.7 3.6

指定index

复制代码
    pd.DataFrame(pop, index=[2001, 2002, 2003])
Nevada Ohio
2001 2.4 1.7
2002 2.9 3.6
2003 NaN NaN

series组成的dict

复制代码
    pdata = {'Ohio': frame3['Ohio'][:-1],
         'Nevada': frame3['Nevada'][:2]}
复制代码
    pd.DataFrame(pdata)
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7

如果DataFrameindexcolumn有自己的name属性,也会被显示:

复制代码
    frame3.index.name = 'year'; frame3.columns.name = 'state'
复制代码
    frame3
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6

values属性会返回二维数组:

复制代码
    frame3.values
复制代码
    array([[ nan,  1.5],
       [ 2.4,  1.7],
       [ 2.9,  3.6]])

如果column有不同的类型,dtype会适应所有的列:

复制代码
    frame2.values
复制代码
    array([[2000, 'Ohio', 1.5, nan],
       [2001, 'Ohio', 1.7, -1.2],
       [2002, 'Ohio', 3.6, nan],
       [2001, 'Nevada', 2.4, -1.5],
       [2002, 'Nevada', 2.9, -1.7],
       [2003, 'Nevada', 3.2, nan]], dtype=object)

3 Index Objects (索引对象)

pandas中的Index Objects(索引对象)负责存储axis labels以及一些附加数据,例如axis namenames。当一个数组或序列被用于构建seriesDataFrame时,会自动被转换为index

复制代码
    obj = pd.Series(range(3), index=['a', 'b', 'c'])
复制代码
    index = obj.index
    index
复制代码
    Index(['a', 'b', 'c'], dtype='object')
复制代码
    index[1:]
复制代码
    Index(['b', 'c'], dtype='object')

index object是不可更改的:

复制代码
    index[1] = 'd'
复制代码
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-67-676fdeb26a68> in <module>()
    ----> 1 index[1] = 'd'
    
    
    /Users/xu/anaconda/envs/py35/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value)
       1243 
       1244     def __setitem__(self, key, value):
    -> 1245         raise TypeError("Index does not support mutable operations")
       1246 
       1247     def __getitem__(self, key):
    
    
    TypeError: Index does not support mutable operations

正因为不可修改,所以data structure中分享index object是很安全的:

复制代码
    labels = pd.Index(np.arange(3))
    labels
复制代码
    Int64Index([0, 1, 2], dtype='int64')
复制代码
    obj2 = pd.Series([1.5, -2.5, 0], index=labels)
    obj2
复制代码
    0    1.5
    1   -2.5
    2    0.0
    dtype: float64
复制代码
    obj2.index is labels
复制代码
    True

index除了想数组,还能像大小一定的set

复制代码
    frame3
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
复制代码
    frame3.columns
复制代码
    Index(['Nevada', 'Ohio'], dtype='object', name='state')
复制代码
    'Ohio' in frame3.columns
复制代码
    True
复制代码
    2003 in frame3.columns
复制代码
    False

python里的set不同,pandasindex可以有重复的labels

复制代码
    dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
    dup_labels
复制代码
    Index(['foo', 'foo', 'bar', 'bar'], dtype='object')

在这种重复的标签中选择的话,会选中所有相同的标签。

全部评论 (0)

还没有任何评论哟~