pandas0.24.1文档3.3 基础功能(二)

作者: Lykit01 | 来源:发表于2019-04-01 14:31 被阅读16次

    目录:
    1 0.24.1版本新特性
    2 安装
    3马上开始
    3.1 pandas概况
    3.2 十分钟上手pandas
    3.3 基础功能(一)
    3.3 基础功能(二)

    3.3.6 函数应用

    如果要对pandas对象应用你自定义的函数或者第三方库的函数,必须了解以下三种方法。应用的方法合不合适取决于你的函数作用的具体对象:是整个DataFrame或Series,还是行或列,或者是每个元素?
    1.应用表函数pipe()
    2.应用行/列函数apply()
    3.聚合接口agg()transform()
    4.应用元素函数applymap()

    3.3.6.1 应用表函数

    DataFrame和Series当然能直接传递给函数作用。但是,如果要连续调用多个函数,建议使用pipe()方法。比较下面两种方法:

    # f, g, and h are functions taking and returning ``DataFrames``
    >>> f(g(h(df), arg1=1), arg2=2, arg3=3)
    

    和下面的方法等价:

    >>> (df.pipe(h)
    ...    .pipe(g, arg1=1)
    ...    .pipe(f, arg2=2, arg3=3))
    

    pandas推荐使用第二种方式,它被叫做方法链。pipe方法让方法链中的各种函数的使用变得简单,包括自定义、第三方库或pandas自带的函数。
    在上面的例子中,f、g和h函数都把DataFrame作为第一个参数。如果你的函数把DataFrame作为第二个参数会怎么样呢?在这种情况下,给pipe函数传入一个元组(callable,data_keyword)。.pipe将会把DataFrame放入元组中指定的参数位置上。
    例如,我们能够用statsmodels库来做统计回归。他们的接口要求第一个参数是公式,第二个是数据。我们把函数、关键字对(sm.ols,'data')传给pipe:

    
    In [142]: import statsmodels.formula.api as sm
    
    In [143]: bb = pd.read_csv('data/baseball.csv', index_col='id')
    
    In [144]: (bb.query('h > 0')   .....:    .assign(ln_h=lambda df: np.log(df.h))   .....:    .pipe((sm.ols, 'data'), 'hr ~ ln_h + year + g + C(lg)')   .....:    .fit()   .....:    .summary()   .....:  )   .....: Out[144]: <class 'statsmodels.iolib.summary.Summary'>"""                            OLS Regression Results                            ==============================================================================Dep. Variable:                     hr   R-squared:                       0.685Model:                            OLS   Adj. R-squared:                  0.665Method:                 Least Squares   F-statistic:                     34.28Date:                Tue, 12 Mar 2019   Prob (F-statistic):           3.48e-15Time:                        22:38:35   Log-Likelihood:                -205.92No. Observations:                  68   AIC:                             421.8Df Residuals:                      63   BIC:                             432.9Df Model:                           4                                         Covariance Type:            nonrobust                                         ===============================================================================                  coef    std err          t      P>|t|      [0.025      0.975]-------------------------------------------------------------------------------Intercept   -8484.7720   4664.146     -1.819      0.074   -1.78e+04     835.780C(lg)[T.NL]    -2.2736      1.325     -1.716      0.091      -4.922       0.375ln_h           -1.3542      0.875     -1.547      0.127      -3.103       0.395year            4.2277      2.324      1.819      0.074      -0.417       8.872g               0.1841      0.029      6.258      0.000       0.125       0.243==============================================================================Omnibus:                       10.875   Durbin-Watson:                   1.999
    Prob(Omnibus):                  0.004   Jarque-Bera (JB):               17.298Skew:                           0.537   Prob(JB):                     0.000175
    Kurtosis:                       5.225   Cond. No.                     1.49e+07
    ==============================================================================
    
    Warnings:
    [1] Standard Errors assume that the covariance matrix of the errors is correctly specified.[2] The condition number is large, 1.49e+07. This might indicate that there arestrong multicollinearity or other numerical problems."""
    

    pipe方法的灵感来自于Unix pipes和最近的dplyrmagritr,后者为R引入了流行的(%>%)运算符(read Pipe)。这里的Pipe实现非常干净,在Python中感觉很好。我们鼓励您查看pipe()的源代码。

    3.3.6.2 应用行/列函数

    通过apply()方法能沿着指定轴对DataFrame的元素应用任意函数。apply()就像统计描述的函数一样,也接受一个可选的axis参数。

    In [145]: df.apply(np.mean)
    Out[145]: 
    one      0.613869
    two      0.470270
    three   -0.427633
    dtype: float64
    
    In [146]: df.apply(np.mean, axis=1)
    Out[146]: 
    a   -0.121116
    b    0.361488
    c    0.571564
    d   -0.058569
    dtype: float64
    
    In [147]: df.apply(lambda x: x.max() - x.min())
    Out[147]: 
    one      1.757280
    two      3.196734
    three    2.065853
    dtype: float64
    
    In [148]: df.apply(np.cumsum)
    Out[148]: 
            one       two     three
    a  1.400810 -1.643041       NaN
    b  1.044340 -0.597130  0.395023
    c  1.841608  0.327385  0.387933
    d       NaN  1.881078 -1.282898
    
    In [149]: df.apply(np.exp)
    Out[149]: 
            one       two     three
    a  4.058485  0.193391       NaN
    b  0.700143  2.845991  1.484418
    c  2.219469  2.520646  0.992935
    d       NaN  4.728902  0.188091
    

    np.exp(x)返回自然底数e的x次方。

    apply()也能通过函数名的字符串调用函数。

    In [150]: df.apply('mean')
    Out[150]: 
    one      0.613869
    two      0.470270
    three   -0.427633
    dtype: float64
    
    In [151]: df.apply('mean', axis=1)
    Out[151]: 
    a   -0.121116
    b    0.361488
    c    0.571564
    d   -0.058569
    dtype: float64
    

    传入apply()的函数的输出结果会影响DataFrame.apply()的最后输出结果,并遵从以下规则:

    • 如果应用的函数返回一个Series,那么最终的输出结果是DataFrame。DataFrame的列会和应用的函数返回Series的索引对齐。
    • 如果应用的函数返回其他类型的数据,那么最终的输出结果是Series。
      通过result_type能够对默认行为进行覆盖,result_type可选参数有reduce、broadcast和expand。这将决定列表类型的输出结果是否和如何转换到DataFrame格式。
      apply()函数加上一点巧思就能对数据集做很多事。比如,我们想要对每一列提取出最大值出现的日期:
    In [152]: tsdf = pd.DataFrame(np.random.randn(1000, 3), columns=['A', 'B', 'C'],
       .....:                     index=pd.date_range('1/1/2000', periods=1000))
       .....: 
    
    In [153]: tsdf.apply(lambda x: x.idxmax())
    Out[153]: 
    A   2000-06-10
    B   2001-07-04
    C   2002-08-09
    dtype: datetime64[ns]
    

    你也可以给apply()方法传递额外的参数和关键字。假设你要应用下面的函数:

    def subtract_and_divide(x, sub, divide=1):
        return (x - sub) / divide
    

    你可以按下面的方式应用这个函数:

    df.apply(subtract_and_divide, args=(5,), divide=3)
    

    另一个有用的功能便是传递Series方法来对每行/列进行Series操作:

    In [154]: tsdf
    Out[154]: 
                       A         B         C
    2000-01-01 -0.652077 -0.239118  0.841272
    2000-01-02  0.130224  0.347505 -0.385666
    2000-01-03 -1.700237 -0.925899  0.199564
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08  0.339319 -0.978307  0.689492
    2000-01-09  0.601495 -0.630417 -1.040079
    2000-01-10  1.511723 -0.427952 -0.400154
    
    In [155]: tsdf.apply(pd.Series.interpolate)
    Out[155]: 
                       A         B         C
    2000-01-01 -0.652077 -0.239118  0.841272
    2000-01-02  0.130224  0.347505 -0.385666
    2000-01-03 -1.700237 -0.925899  0.199564
    2000-01-04 -1.292326 -0.936380  0.297550
    2000-01-05 -0.884415 -0.946862  0.395535
    2000-01-06 -0.476503 -0.957344  0.493521
    2000-01-07 -0.068592 -0.967825  0.591507
    2000-01-08  0.339319 -0.978307  0.689492
    2000-01-09  0.601495 -0.630417 -1.040079
    2000-01-10  1.511723 -0.427952 -0.400154
    

    apply()还有一个参数raw,默认为false,在应用函数前会先把没行/列转换成一个Series。如果设置参数raw为true,要应用的函数会接收到一个n维数组(ndarray)对象,这样会带来潜在的性能提升,如果你不需要索引功能的话。

    3.3.6.3 聚合接口(Aggregation API)

    这是0.20.0版本的新特性。
    聚合接口允许用户通过简单的方法同时传递多个聚合操作。这个API接口在pandas对象中是非常类似的,请看分组group API窗口函数window functions API重采样resample API。聚合的使用方法是DataFrame.aggregate()或别名DataFrame.agg()
    我们使用和上面类似的DataFrame来说明:

    In [156]: tsdf = pd.DataFrame(np.random.randn(10, 3), columns=['A', 'B', 'C'],
       .....:                     index=pd.date_range('1/1/2000', periods=10))
       .....: 
    
    In [157]: tsdf.iloc[3:7] = np.nan
    
    In [158]: tsdf
    Out[158]: 
                       A         B         C
    2000-01-01  0.396575 -0.364907  0.051290
    2000-01-02 -0.310517 -0.369093 -0.353151
    2000-01-03 -0.522441  1.659115 -0.272364
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08 -0.057890  1.148901  0.011528
    2000-01-09 -0.155578  0.742150  0.107324
    2000-01-10  0.531797  0.080254  0.833297
    

    使用单个函数时,agg()和apply()是等价的。你也可以直接传入函数名的字符串。这就返回一个包含聚合结果的Series:

    In [159]: tsdf.agg(np.sum)
    Out[159]: 
    A   -0.118055
    B    2.896420
    C    0.377923
    dtype: float64
    
    In [160]: tsdf.agg('sum')
    Out[160]: 
    A   -0.118055
    B    2.896420
    C    0.377923
    dtype: float64
    
    # these are equivalent to a ``.sum()`` because we are aggregating
    # on a single function
    In [161]: tsdf.sum()
    Out[161]: 
    A   -0.118055
    B    2.896420
    C    0.377923
    dtype: float64
    

    对Series使用单个聚合会返回一个标量值:

    In [162]: tsdf.A.agg('sum')
    Out[162]: -0.11805495013260869
    
    3.3.6.4 通过多个函数进行聚合

    你能通过列表的方式来传递多个聚合操作参数。每个聚合函数的结果将会是产生的DataFrame的一列。行名会用聚合函数的名字命名:

    In [163]: tsdf.agg(['sum'])
    Out[163]: 
                A        B         C
    sum -0.118055  2.89642  0.377923
    

    多个函数返回多行结果:

    In [164]: tsdf.agg(['sum', 'mean'])
    Out[164]: 
                 A         B         C
    sum  -0.118055  2.896420  0.377923
    mean -0.019676  0.482737  0.062987
    

    对于Series,多个函数返回一个Series,索引则是函数名:

    In [165]: tsdf.A.agg(['sum', 'mean'])
    Out[165]: 
    sum    -0.118055
    mean   -0.019676
    Name: A, dtype: float64
    

    传递一个lambda函数将会返回一个<lambda>命名的行:

    In [166]: tsdf.A.agg(['sum', lambda x: x.mean()])
    Out[166]: 
    sum        -0.118055
    <lambda>   -0.019676
    Name: A, dtype: float64
    

    传递一个自定义的函数将会返回函数名命名的行:

    In [167]: def mymean(x):
       .....:     return x.mean()
       .....: 
    
    In [168]: tsdf.A.agg(['sum', mymean])
    Out[168]: 
    sum      -0.118055
    mymean   -0.019676
    Name: A, dtype: float64
    
    3.3.6.5 通过字典进行聚合

    你可以给DataFrame.agg函数传入一个列名到标量或标量表的字典,这样可以自定义哪些函数作用哪些函数。注意这样产生的结果并没有特定的顺序,你可以使用OrderedDict来保证排序。

    In [169]: tsdf.agg({'A': 'mean', 'B': 'sum'})
    Out[169]: 
    A   -0.019676
    B    2.896420
    dtype: float64
    

    对一个列传递一个列表的方法将会产生一个DataFrame。对于所有的聚合函数将会得到一个矩阵格式的结果。结果将包含所有的聚合函数。函数没有指定的列的位置将是NaN。

    In [170]: tsdf.agg({'A': ['mean', 'min'], 'B': 'sum'})
    Out[170]: 
                 A        B
    mean -0.019676      NaN
    min  -0.522441      NaN
    sum        NaN  2.89642
    
    3.3.6.6 混合数据类型

    当遇到混合数据类型的DataFrame时,不能直接聚合,.agg()将只作用于能够聚合的值。这和分组(groupby)的.agg工作原理类似:

    In [171]: mdf = pd.DataFrame({'A': [1, 2, 3],
       .....:                     'B': [1., 2., 3.],
       .....:                     'C': ['foo', 'bar', 'baz'],
       .....:                     'D': pd.date_range('20130101', periods=3)})
       .....: 
    
    In [172]: mdf.dtypes
    Out[172]: 
    A             int64
    B           float64
    C            object
    D    datetime64[ns]
    dtype: object
    
    In [173]: mdf.agg(['min', 'sum'])
    Out[173]: 
         A    B          C          D
    min  1  1.0        bar 2013-01-01
    sum  6  6.0  foobarbaz        NaT
    
    3.3.6.7 自定义描述函数

    使用.agg()可以轻松创建自定义描述函数,类似于内置的描述函数。

    In [174]: from functools import partial
    
    In [175]: q_25 = partial(pd.Series.quantile, q=0.25)
    
    In [176]: q_25.__name__ = '25%'
    
    In [177]: q_75 = partial(pd.Series.quantile, q=0.75)
    
    In [178]: q_75.__name__ = '75%'
    
    In [179]: tsdf.agg(['count', 'mean', 'std', 'min', q_25, 'median', q_75, 'max'])
    Out[179]: 
                   A         B         C
    count   6.000000  6.000000  6.000000
    mean   -0.019676  0.482737  0.062987
    std     0.408577  0.836785  0.420419
    min    -0.522441 -0.369093 -0.353151
    25%    -0.271782 -0.253617 -0.201391
    median -0.106734  0.411202  0.031409
    75%     0.282958  1.047213  0.093315
    max     0.531797  1.659115  0.833297
    
    3.3.6.8 转换接口(Transform API)

    这是0.20.0版本的新特性。
    transform()方法会返回一个和原数据相同大小和同样索引的对象。它的接口允许你同时提供多个操作而不是一个一个传递函数。这和.agg的接口很类似。
    我们用一个和上面用过的DataFrame类似的对象来说明:

    In [180]: tsdf = pd.DataFrame(np.random.randn(10, 3), columns=['A', 'B', 'C'],
       .....:                     index=pd.date_range('1/1/2000', periods=10))
       .....: 
    
    In [181]: tsdf.iloc[3:7] = np.nan
    
    In [182]: tsdf
    Out[182]: 
                       A         B         C
    2000-01-01 -1.219234 -1.652700 -0.698277
    2000-01-02  1.858653 -0.738520  0.630364
    2000-01-03 -0.112596  1.525897  1.364225
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08 -0.527790 -1.715506  0.387274
    2000-01-09 -0.569341  0.569386  0.134136
    2000-01-10 -0.413993 -0.862280  0.662690
    

    转换整个数据结构。.transform()允许传入的函数有:NumPy函数、函数名字符串或者用户自定义函数。

    In [183]: tsdf.transform(np.abs)
    Out[183]: 
                       A         B         C
    2000-01-01  1.219234  1.652700  0.698277
    2000-01-02  1.858653  0.738520  0.630364
    2000-01-03  0.112596  1.525897  1.364225
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08  0.527790  1.715506  0.387274
    2000-01-09  0.569341  0.569386  0.134136
    2000-01-10  0.413993  0.862280  0.662690
    
    In [184]: tsdf.transform('abs')
    Out[184]: 
                       A         B         C
    2000-01-01  1.219234  1.652700  0.698277
    2000-01-02  1.858653  0.738520  0.630364
    2000-01-03  0.112596  1.525897  1.364225
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08  0.527790  1.715506  0.387274
    2000-01-09  0.569341  0.569386  0.134136
    2000-01-10  0.413993  0.862280  0.662690
    
    In [185]: tsdf.transform(lambda x: x.abs())
    Out[185]: 
                       A         B         C
    2000-01-01  1.219234  1.652700  0.698277
    2000-01-02  1.858653  0.738520  0.630364
    2000-01-03  0.112596  1.525897  1.364225
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08  0.527790  1.715506  0.387274
    2000-01-09  0.569341  0.569386  0.134136
    2000-01-10  0.413993  0.862280  0.662690
    

    这里transform()只接收了一个函数。这等价于ufunc应用。

    ufunc:universal function,对数组的每个元素进行运算的函数。NumPy的许多函数都是如此。

    In [186]: np.abs(tsdf)
    Out[186]: 
                       A         B         C
    2000-01-01  1.219234  1.652700  0.698277
    2000-01-02  1.858653  0.738520  0.630364
    2000-01-03  0.112596  1.525897  1.364225
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08  0.527790  1.715506  0.387274
    2000-01-09  0.569341  0.569386  0.134136
    2000-01-10  0.413993  0.862280  0.662690
    

    对单个Series使用transform()并只传入一个函数,这样就会返回单个Series。

    In [187]: tsdf.A.transform(np.abs)
    Out[187]: 
    2000-01-01    1.219234
    2000-01-02    1.858653
    2000-01-03    0.112596
    2000-01-04         NaN
    2000-01-05         NaN
    2000-01-06         NaN
    2000-01-07         NaN
    2000-01-08    0.527790
    2000-01-09    0.569341
    2000-01-10    0.413993
    Freq: D, Name: A, dtype: float64
    
    3.3.6.9 通过多个函数进行转换

    传递多个函数给transform()将会返回一个有多重索引的列的DataFrame。列的第一层将是原始的列名,第二层将是传入的函数的名字。

    In [188]: tsdf.transform([np.abs, lambda x: x + 1])
    Out[188]: 
                       A                   B                   C          
                absolute  <lambda>  absolute  <lambda>  absolute  <lambda>
    2000-01-01  1.219234 -0.219234  1.652700 -0.652700  0.698277  0.301723
    2000-01-02  1.858653  2.858653  0.738520  0.261480  0.630364  1.630364
    2000-01-03  0.112596  0.887404  1.525897  2.525897  1.364225  2.364225
    2000-01-04       NaN       NaN       NaN       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN       NaN       NaN       NaN
    2000-01-08  0.527790  0.472210  1.715506 -0.715506  0.387274  1.387274
    2000-01-09  0.569341  0.430659  0.569386  1.569386  0.134136  1.134136
    2000-01-10  0.413993  0.586007  0.862280  0.137720  0.662690  1.662690
    

    对一个Series传入多个函数会产生一个DataFrame。产生的列名将是传入的函数名。

    In [189]: tsdf.A.transform([np.abs, lambda x: x + 1])
    Out[189]: 
                absolute  <lambda>
    2000-01-01  1.219234 -0.219234
    2000-01-02  1.858653  2.858653
    2000-01-03  0.112596  0.887404
    2000-01-04       NaN       NaN
    2000-01-05       NaN       NaN
    2000-01-06       NaN       NaN
    2000-01-07       NaN       NaN
    2000-01-08  0.527790  0.472210
    2000-01-09  0.569341  0.430659
    2000-01-10  0.413993  0.586007
    
    3.3.6.10 通过字典进行转换

    通过传递函数的字典将能自定义对哪些列使用哪些函数。

    In [190]: tsdf.transform({'A': np.abs, 'B': lambda x: x + 1})
    Out[190]: 
                       A         B
    2000-01-01  1.219234 -0.652700
    2000-01-02  1.858653  0.261480
    2000-01-03  0.112596  2.525897
    2000-01-04       NaN       NaN
    2000-01-05       NaN       NaN
    2000-01-06       NaN       NaN
    2000-01-07       NaN       NaN
    2000-01-08  0.527790 -0.715506
    2000-01-09  0.569341  1.569386
    2000-01-10  0.413993  0.137720
    

    如果对一个列传递了多个函数(字典里用列表表示),将会产生一个多层索引的DataFrame,列名也将是传入的函数。

    In [191]: tsdf.transform({'A': np.abs, 'B': [lambda x: x + 1, 'sqrt']})
    Out[191]: 
                       A         B          
                absolute  <lambda>      sqrt
    2000-01-01  1.219234 -0.652700       NaN
    2000-01-02  1.858653  0.261480       NaN
    2000-01-03  0.112596  2.525897  1.235272
    2000-01-04       NaN       NaN       NaN
    2000-01-05       NaN       NaN       NaN
    2000-01-06       NaN       NaN       NaN
    2000-01-07       NaN       NaN       NaN
    2000-01-08  0.527790 -0.715506       NaN
    2000-01-09  0.569341  1.569386  0.754577
    2000-01-10  0.413993  0.137720       NaN
    
    3.3.6.11 应用元素函数

    并不是所有的函数都能矢量化(接受NumPy数组并且返回另一个数组或者值),DataFrame的applumap()方法和Series的map()方法能够接受python的任何函数(接收单个值并返回单个值的函数)。比如:

    In [192]: df4
    Out[192]: 
            one       two     three
    a  1.400810 -1.643041       NaN
    b -0.356470  1.045911  0.395023
    c  0.797268  0.924515 -0.007090
    d       NaN  1.553693 -1.670830
    
    In [193]: def f(x):
       .....:     return len(str(x))
       .....: 
    
    In [194]: df4['one'].map(f)
    Out[194]: 
    a    18
    b    19
    c    18
    d     3
    Name: one, dtype: int64
    
    In [195]: df4.applymap(f)
    Out[195]: 
       one  two  three
    a   18   19      3
    b   19   18     19
    c   18   18     21
    d    3   18     19
    

    Series.map()有额外的特性,它能连接(link)/映射(map)其他Series。这和合并函数有关:

    In [196]: s = pd.Series(['six', 'seven', 'six', 'seven', 'six'],
       .....:               index=['a', 'b', 'c', 'd', 'e'])
       .....: 
    
    In [197]: t = pd.Series({'six': 6., 'seven': 7.})
    
    In [198]: s
    Out[198]: 
    a      six
    b    seven
    c      six
    d    seven
    e      six
    dtype: object
    
    In [199]: s.map(t)
    Out[199]: 
    a    6.0
    b    7.0
    c    6.0
    d    7.0
    e    6.0
    dtype: float64
    

    3.3.7 重新索引和改变标签

    reindex()是pandas中基本的数据对齐方法。它被用来实现几乎所有基于标签对齐的函数特性。reindex意味着使数据与特定轴上的一组给定标签相匹配。 它做了下面几件事:

    • 对数据重新排序,与新的标签匹配
    • 如果标签的位置没有数据,就插入缺失值(NA)
    • 如果指定了,则使用逻辑(与处理时间序列数据高度相关)填充缺失标签的数据。
      下面是一个简单的例子:
    In [200]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
    
    In [201]: s
    Out[201]: 
    a   -0.368437
    b   -0.036473
    c    0.774830
    d   -0.310545
    e    0.709717
    dtype: float64
    
    In [202]: s.reindex(['e', 'b', 'f', 'd'])
    Out[202]: 
    e    0.709717
    b   -0.036473
    f         NaN
    d   -0.310545
    dtype: float64
    

    上面的Series中原本不包含“f”标签,因此结果出现了NaN值。
    对于DataFrame,你能够同时对index和columns进行重新索引:

    In [203]: df
    Out[203]: 
            one       two     three
    a  1.400810 -1.643041       NaN
    b -0.356470  1.045911  0.395023
    c  0.797268  0.924515 -0.007090
    d       NaN  1.553693 -1.670830
    
    In [204]: df.reindex(index=['c', 'f', 'b'], columns=['three', 'two', 'one'])
    Out[204]: 
          three       two       one
    c -0.007090  0.924515  0.797268
    f       NaN       NaN       NaN
    b  0.395023  1.045911 -0.356470
    

    也可以通过axis关键字来指定要重新索引的轴。

    In [205]: df.reindex(['c', 'f', 'b'], axis='index')
    Out[205]: 
            one       two     three
    c  0.797268  0.924515 -0.007090
    f       NaN       NaN       NaN
    b -0.356470  1.045911  0.395023
    

    注意包含实际轴标签的索引可以在对象之间共享。如果我们有一个Series和DataFrame,可以做下面的操作:

    In [206]: rs = s.reindex(df.index)
    
    In [207]: rs
    Out[207]: 
    a   -0.368437
    b   -0.036473
    c    0.774830
    d   -0.310545
    dtype: float64
    
    In [208]: rs.index is df.index
    Out[208]: True
    

    这意味着重新索引得到的Series的索引和DataFrame的索引是同一个对象。

    下面是0.21.0版本的新特性。
    DataFrame.reindex()还支持轴风格(axis-style)的调用约定,即你可以指定单个标签参数及其应用的轴。

    In [209]: df.reindex(['c', 'f', 'b'], axis='index')
    Out[209]: 
            one       two     three
    c  0.797268  0.924515 -0.007090
    f       NaN       NaN       NaN
    b -0.356470  1.045911  0.395023
    
    In [210]: df.reindex(['three', 'two', 'one'], axis='columns')
    Out[210]: 
          three       two       one
    a       NaN -1.643041  1.400810
    b  0.395023  1.045911 -0.356470
    c -0.007090  0.924515  0.797268
    d -1.670830  1.553693       NaN
    

    另见:MultiIndex/Advanced Indexing,这是完成重新索引操作更简单的方法。
    注意:在编写性能敏感的代码时,有一个很好的理由花一些时间成为一个重新索引的忍者(不要直接用重新索引):许多操作在预先对齐的数据上更快。 加和两个未对齐的DataFrame会触发重新索引步骤。对于探索性分析,您几乎不会注意到差异(因为reindex已经进行了大量优化),但是当CPU运行效率很重要时,在这里进行一些直接的reindex调用可能会产生影响。

    3.3.7.1 重新索引来和另一对象对齐

    你可能会想把一个对象的轴标签变得和另一个一样。虽然直接操作语法简单,但是很冗长,既然这是一个非常常见的操作,我们可以使用reindex_like()方法来简化它:

    In [211]: df2
    Out[211]: 
            one       two
    a  1.400810 -1.643041
    b -0.356470  1.045911
    c  0.797268  0.924515
    
    In [212]: df3
    Out[212]: 
            one       two
    a  0.786941 -1.752170
    b -0.970339  0.936783
    c  0.183399  0.815387
    
    In [213]: df.reindex_like(df2)
    Out[213]: 
            one       two
    a  1.400810 -1.643041
    b -0.356470  1.045911
    c  0.797268  0.924515
    
    3.3.7.2 通过align方法对齐对象

    同时对齐两个对象最快的途径就是使用align()方法。它支持join参数(和连接和合并有关):

    • join='outer':取索引的并集(默认)
    • join='left':使用调用对象的索引
    • join='right':使用传入的对象的索引
    • join='inner':索引的交集
      它返回带有两个重新索引的Series的元组。
    In [214]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
    
    In [215]: s1 = s[:4]
    
    In [216]: s2 = s[1:]
    
    In [217]: s1.align(s2)
    Out[217]: 
    (a   -0.610263
     b   -0.170883
     c    0.367255
     d    0.273860
     e         NaN
     dtype: float64,
     a         NaN
     b   -0.170883
     c    0.367255
     d    0.273860
     e    0.314782
     dtype: float64)
    
    In [218]: s1.align(s2, join='inner')
    Out[218]: 
    (b   -0.170883
     c    0.367255
     d    0.273860
     dtype: float64,
     b   -0.170883
     c    0.367255
     d    0.273860
     dtype: float64)
    
    In [219]: s1.align(s2, join='left')
    Out[219]: 
    (a   -0.610263
     b   -0.170883
     c    0.367255
     d    0.273860
     dtype: float64, 
     a         NaN
     b   -0.170883
     c    0.367255
     d    0.273860
     dtype: float64)
    

    对于DataFrame,连接方法将会默认应用到index和columns。

    In [220]: df.align(df2, join='inner')
    Out[220]: 
    (        one       two
     a  1.400810 -1.643041
     b -0.356470  1.045911
     c  0.797268  0.924515,
     one       two
     a  1.400810 -1.643041
     b -0.356470  1.045911
     c  0.797268  0.924515)
    

    你也可以传入可选的axis参数来指定要对齐的轴:

    In [221]: df.align(df2, join='inner', axis=0)
    Out[221]: 
    (        one       two     three
     a  1.400810 -1.643041       NaN
     b -0.356470  1.045911  0.395023
     c  0.797268  0.924515 -0.007090,
     one       two
     a  1.400810 -1.643041
     b -0.356470  1.045911
     c  0.797268  0.924515)
    

    如果你将一个Series传入DataFrame.align(),通过axis参数你可以选择是跟DataFrame的index还是columns对齐:

    In [222]: df.align(df2.iloc[0], axis=1)
    Out[222]: 
    (        one     three       two
     a  1.400810       NaN -1.643041
     b -0.356470  0.395023  1.045911
     c  0.797268 -0.007090  0.924515
     d       NaN -1.670830  1.553693,
     one      1.400810
     three         NaN
     two     -1.643041
     Name: a, dtype: float64)
    
    3.3.7.3 重新索引时填充

    reindex()有一个可选的参数——填充方法,可以从下面的表中选择:

    方法 行为
    pad/ffill 向前填充
    bfill/backfill 向后填充
    nearest 从最近索引值填充

    现在我们通过一个简单的Series来解释这些填充方法。

    In [223]: rng = pd.date_range('1/3/2000', periods=8)
    
    In [224]: ts = pd.Series(np.random.randn(8), index=rng)
    
    In [225]: ts2 = ts[[0, 3, 6]]
    
    In [226]: ts
    Out[226]: 
    2000-01-03   -0.082578
    2000-01-04    0.768554
    2000-01-05    0.398842
    2000-01-06   -0.357956
    2000-01-07    0.156403
    2000-01-08   -1.347564
    2000-01-09    0.253506
    2000-01-10    1.228964
    Freq: D, dtype: float64
    
    In [227]: ts2
    Out[227]: 
    2000-01-03   -0.082578
    2000-01-06   -0.357956
    2000-01-09    0.253506
    dtype: float64
    
    In [228]: ts2.reindex(ts.index)
    Out[228]: 
    2000-01-03   -0.082578
    2000-01-04         NaN
    2000-01-05         NaN
    2000-01-06   -0.357956
    2000-01-07         NaN
    2000-01-08         NaN
    2000-01-09    0.253506
    2000-01-10         NaN
    Freq: D, dtype: float64
    
    In [229]: ts2.reindex(ts.index, method='ffill')
    Out[229]: 
    2000-01-03   -0.082578
    2000-01-04   -0.082578
    2000-01-05   -0.082578
    2000-01-06   -0.357956
    2000-01-07   -0.357956
    2000-01-08   -0.357956
    2000-01-09    0.253506
    2000-01-10    0.253506
    Freq: D, dtype: float64
    
    In [230]: ts2.reindex(ts.index, method='bfill')
    Out[230]: 
    2000-01-03   -0.082578
    2000-01-04   -0.357956
    2000-01-05   -0.357956
    2000-01-06   -0.357956
    2000-01-07    0.253506
    2000-01-08    0.253506
    2000-01-09    0.253506
    2000-01-10         NaN
    Freq: D, dtype: float64
    
    In [231]: ts2.reindex(ts.index, method='nearest')
    Out[231]: 
    2000-01-03   -0.082578
    2000-01-04   -0.082578
    2000-01-05   -0.357956
    2000-01-06   -0.357956
    2000-01-07   -0.357956
    2000-01-08    0.253506
    2000-01-09    0.253506
    2000-01-10    0.253506
    Freq: D, dtype: float64
    

    这些方法要求索引是已经按升序或降序排好序了。
    注意通过fillna(没有'nearest'这个方法)或者interpolate方法也可以达到同样的效果。

    In [232]: ts2.reindex(ts.index).fillna(method='ffill')
    Out[232]: 
    2000-01-03   -0.082578
    2000-01-04   -0.082578
    2000-01-05   -0.082578
    2000-01-06   -0.357956
    2000-01-07   -0.357956
    2000-01-08   -0.357956
    2000-01-09    0.253506
    2000-01-10    0.253506
    Freq: D, dtype: float64
    

    做填充时如果index不是单调递增或递减时reindex()会报错。fillna()和interpolate()方法不会对index的索引做如何检查。

    3.3.7.4 重新索引时填充的限制

    重新索引填充时,limit和tolerance参数能做额外限制。limit指定了连续匹配时的最大填充数目。

    In [233]: ts2.reindex(ts.index, method='ffill', limit=1)
    Out[233]: 
    2000-01-03   -0.082578
    2000-01-04   -0.082578
    2000-01-05         NaN
    2000-01-06   -0.357956
    2000-01-07   -0.357956
    2000-01-08         NaN
    2000-01-09    0.253506
    2000-01-10    0.253506
    Freq: D, dtype: float64
    

    而tolerance指定了要填充的索引和有值的索引之间的最大距离。

    In [234]: ts2.reindex(ts.index, method='ffill', tolerance='1 day')
    Out[234]: 
    2000-01-03   -0.082578
    2000-01-04   -0.082578
    2000-01-05         NaN
    2000-01-06   -0.357956
    2000-01-07   -0.357956
    2000-01-08         NaN
    2000-01-09    0.253506
    2000-01-10    0.253506
    Freq: D, dtype: float64
    

    注意如果对DatetimeIndex、TimedeltaIndex或PeriodIndex使用填充时,如果可能tolerance参数将被强制转换成Timedelta。这允许你用合适的字符串指定tolerance参数。

    3.3.7.5 在轴上删除标签

    和reindex比较相关的方法是drop()函数。它会移除轴上的一些标签。

    In [235]: df
    Out[235]: 
            one       two     three
    a  1.400810 -1.643041       NaN
    b -0.356470  1.045911  0.395023
    c  0.797268  0.924515 -0.007090
    d       NaN  1.553693 -1.670830
    
    In [236]: df.drop(['a', 'd'], axis=0)
    Out[236]: 
            one       two     three
    b -0.356470  1.045911  0.395023
    c  0.797268  0.924515 -0.007090
    
    In [237]: df.drop(['one'], axis=1)
    Out[237]: 
            two     three
    a -1.643041       NaN
    b  1.045911  0.395023
    c  0.924515 -0.007090
    d  1.553693 -1.670830
    

    注意下面的方法也可行,但是不那么简洁明确:

    In [238]: df.reindex(df.index.difference(['a', 'd']))
    Out[238]: 
            one       two     three
    b -0.356470  1.045911  0.395023
    c  0.797268  0.924515 -0.007090
    
    3.3.7.6 重命名/映射标签

    rename()允许你基于一些映射(比如字典或Series)或其他函数来给轴重新打上标签。

    In [239]: s
    Out[239]: 
    a   -0.610263
    b   -0.170883
    c    0.367255
    d    0.273860
    e    0.314782
    dtype: float64
    
    In [240]: s.rename(str.upper)
    Out[240]: 
    A   -0.610263
    B   -0.170883
    C    0.367255
    D    0.273860
    E    0.314782
    dtype: float64
    

    当传入一个函数时,函数必须能对所有标签都返回一个值(而且必须是唯一值)。也可以用字典或者Series。

    In [241]: df.rename(columns={'one': 'foo', 'two': 'bar'},
       .....:           index={'a': 'apple', 'b': 'banana', 'd': 'durian'})
       .....: 
    Out[241]: 
                 foo       bar     three
    apple   1.400810 -1.643041       NaN
    banana -0.356470  1.045911  0.395023
    c       0.797268  0.924515 -0.007090
    durian       NaN  1.553693 -1.670830
    

    如果一个行/列标签在映射中没有,那么就不会被重命名。注意,映射中多余的标签并不会报错。

    下面是0.21.0版本的新特性。
    DataFrame.rename()也支持轴风格(axis-style)的调用约定,即你可以指定单个映射及其映射的轴。

    In [242]: df.rename({'one': 'foo', 'two': 'bar'}, axis='columns')
    Out[242]: 
            foo       bar     three
    a  1.400810 -1.643041       NaN
    b -0.356470  1.045911  0.395023
    c  0.797268  0.924515 -0.007090
    d       NaN  1.553693 -1.670830
    
    In [243]: df.rename({'a': 'apple', 'b': 'banana', 'd': 'durian'}, axis='index')
    Out[243]: 
                 one       two     three
    apple   1.400810 -1.643041       NaN
    banana -0.356470  1.045911  0.395023
    c       0.797268  0.924515 -0.007090
    durian       NaN  1.553693 -1.670830
    

    rename()方法也提供了一个inplace参数,默认为False,即在原数据的副本上进行相关操作。传入inplace=True会直接对原数据进行更改。

    下面是0.18.0版本的新特性。
    最后,rename()也接受一个或多个标量值来更改Series的.name属性。

    In [244]: s.rename("scalar-name")
    Out[244]: 
    a   -0.610263
    b   -0.170883
    c    0.367255
    d    0.273860
    e    0.314782
    Name: scalar-name, dtype: float64
    

    下面是0.24.0版本的新特性。
    rename_axis()rename_axis()允许指定要改变的多层索引的名字。

    In [245]: df = pd.DataFrame({'x': [1, 2, 3, 4, 5, 6],
       .....:                    'y': [10, 20, 30, 40, 50, 60]},
       .....:                   index=pd.MultiIndex.from_product([['a', 'b', 'c'], [1, 2]],
       .....:                   names=['let', 'num']))
       .....: 
    
    In [246]: df
    Out[246]: 
             x   y
    let num       
    a   1    1  10
        2    2  20
    b   1    3  30
        2    4  40
    c   1    5  50
        2    6  60
    
    In [247]: df.rename_axis(index={'let': 'abc'})
    Out[247]: 
             x   y
    abc num       
    a   1    1  10
        2    2  20
    b   1    3  30
        2    4  40
    c   1    5  50
        2    6  60
    
    In [248]: df.rename_axis(index=str.upper)
    Out[248]: 
             x   y
    LET NUM       
    a   1    1  10
        2    2  20
    b   1    3  30
        2    4  40
    c   1    5  50
        2    6  60
    

    3.3.8 迭代(Iteration)

    pandas不同类型的对象迭代返回的结果不同。Series迭代时会被看作数组,会返回一个个值。而对于DataFrame和Panel这种数据结构,会遵循字典迭代的约定,会返回对象的“keys”。
    简而言之,基本的迭代操作会产生如下结果:

    • Series:值
    • DataFrame:column标签
    • Panel:item标签
      下面举个例子,对DataFrame进行迭代会返回给你列名:
    In [249]: df = pd.DataFrame({'col1': np.random.randn(3),
       .....:                    'col2': np.random.randn(3)}, index=['a', 'b', 'c'])
       .....: 
    
    In [250]: for col in df:
       .....:     print(col)
       .....: 
    col1
    col2
    

    pandas对象也有类似于字典iteritems()的方法去对(key,value)对进行迭代。
    要对DataFrame的行进行迭代,可以使用以下方法:

    • iterrows():对DataFrame的行进行迭代,返回(index,Series)对。这把rows转换为Series对象,可能会改变原来的数据类型,但也能带来一些性能提升。
    • itertuples():对DataFrame的行进行迭代,返回命名了的元组。这比iterrows()快读了,并且在很多情况下如果要对DataFrame的值进行迭代,推荐使用这种方法。

    itertuples这么说有点抽象,往后看,后面有详细的描述。

    警告: 对pandas对象进行迭代通常非常慢。在很多情况下,并不需要对行进行迭代,而且可以用下面的方法进行避免。

    • 寻找矢量化的解决方法:很多操作都能使用内置的方法、NumPy函数或者布尔索引
    • 如果有一个能够对DataFrame、Series全局起作用的函数,最好使用apply()方法,而不是对值进行迭代。详情请看函数应用
    • 如果需要对值进行迭代操作而且性能又很重要,考虑用cython或numba写内部循环。具体例子请看增强性能部分
      警告: 对于你迭代的对象,永远不要修改值。修改并不能保证在所有情况下都有效,这取决于数据类型。如果迭代器返回的是副本而不是原数据的视图,修改它将不产生任何效果。
      比如,下面的例子中的赋值是无效的:
    In [251]: df = pd.DataFrame({'a': [1, 2, 3], 'b': ['a', 'b', 'c']})
    
    In [252]: for index, row in df.iterrows():
       .....:     row['a'] = 10
       .....: 
    
    In [253]: df
    Out[253]: 
       a  b
    0  1  a
    1  2  b
    2  3  c
    
    3.3.8.1 iteritems方法

    与字典的交互一致,iteritems()对键值对进行迭代:

    • Series:(index,标量值)对
    • DataFrame:(column,Series)对
    • Panel:(item,DataFrame)对
      举个例子:
    In [254]: for item, frame in wp.iteritems():
       .....:     print(item)
       .....:     print(frame)
       .....: 
    Item1
                       A         B         C         D
    2000-01-01 -1.157892 -1.344312  0.844885  1.075770
    2000-01-02 -0.109050  1.643563 -1.469388  0.357021
    2000-01-03 -0.674600 -1.776904 -0.968914 -1.294524
    2000-01-04  0.413738  0.276662 -0.472035 -0.013960
    2000-01-05 -0.362543 -0.006154 -0.923061  0.895717
    Item2
                       A         B         C         D
    2000-01-01  0.805244 -1.206412  2.565646  1.431256
    2000-01-02  1.340309 -1.170299 -0.226169  0.410835
    2000-01-03  0.813850  0.132003 -0.827317 -0.076467
    2000-01-04 -1.187678  1.130127 -1.436737 -1.413681
    2000-01-05  1.607920  1.024180  0.569605  0.875906
    
    3.3.8.2 iterrows方法

    iterrows()方法允许你像Series对象一样对DataFrame的rows进行迭代。它会返回一个迭代器,会生成index值以及和index一起的包含每行数据的Series。

    In [255]: for row_index, row in df.iterrows():
       .....:     print(row_index, row, sep='\n')
       .....: 
    0
    a    1
    b    a
    Name: 0, dtype: object
    1
    a    2
    b    b
    Name: 1, dtype: object
    2
    a    3
    b    c
    Name: 2, dtype: object
    

    注意: 因为iterrows返回每行的Series,它并不保存行的数据类型。(数据类型保存在DataFrame的每列中)。举个例子:

    In [256]: df_orig = pd.DataFrame([[1, 1.5]], columns=['int', 'float'])
    
    In [257]: df_orig.dtypes
    Out[257]: 
    int        int64
    float    float64
    dtype: object
    
    In [258]: row = next(df_orig.iterrows())[1]
    
    In [259]: row
    Out[259]: 
    int      1.0
    float    1.5
    Name: 0, dtype: float64
    

    返回的Series中的所有值都被转换到了floats数据类型,包括第一列中的整数。

    In [260]: row['int'].dtype
    Out[260]: dtype('float64')
    
    In [261]: df_orig['int'].dtype
    Out[261]: dtype('int64')
    

    如果想要保存数据类型,建议使用itertuples(),它会返回命名的元组,而且比iterrows()快多了。
    比如,一种人为的转换DataFrame的方法可能是:

    In [262]: df2 = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
    
    In [263]: print(df2)
       x  y
    0  1  4
    1  2  5
    2  3  6
    
    In [264]: print(df2.T)
       0  1  2
    x  1  2  3
    y  4  5  6
    
    In [265]: df2_t = pd.DataFrame({idx: values for idx, values in df2.iterrows()})
    
    In [266]: print(df2_t)
       0  1  2
    x  1  2  3
    y  4  5  6
    
    3.3.8.3 itertuples方法

    itertuples()方法会返回迭代器,它会生成DataFrame每行的命名的元组。元组的第一个元素是与行相关的index值,剩下的值是对应的值。
    比如:

    In [267]: for row in df.itertuples():
       .....:     print(row)
       .....: 
    Pandas(Index=0, a=1, b='a')
    Pandas(Index=1, a=2, b='b')
    Pandas(Index=2, a=3, b='c')
    

    这个方法并不把row变为Series,它仅仅以命名的元组返回值。因此,itertuples()会保存值的数据类型,并且会比iterrows()快很多。
    注意: 如果列名称时无效的python标识符、重复的或以下划线开头,那么它们将被重命名为位置名称。如果columns的个数太多(>255),那么将返回一个普通的元组。

    3.3.9 时间访问器(.dt accessor)

    如果Series是类似的日期时间/时间段的Series,那么这个Series有一个访问器,可以方便地返回日期时间这样的属性。返回值也是Series,并和原Series是一样的索引。

    # datetime
    In [268]: s = pd.Series(pd.date_range('20130101 09:10:12', periods=4))
    
    In [269]: s
    Out[269]: 
    0   2013-01-01 09:10:12
    1   2013-01-02 09:10:12
    2   2013-01-03 09:10:12
    3   2013-01-04 09:10:12
    dtype: datetime64[ns]
    
    In [270]: s.dt.hour
    Out[270]: 
    0    9
    1    9
    2    9
    3    9
    dtype: int64
    
    In [271]: s.dt.second
    Out[271]: 
    0    12
    1    12
    2    12
    3    12
    dtype: int64
    
    In [272]: s.dt.day
    Out[272]: 
    0    1
    1    2
    2    3
    3    4
    dtype: int64
    

    这个功能还支持下面的表达式:

    In [273]: s[s.dt.day == 2]
    Out[273]: 
    1   2013-01-02 09:10:12
    dtype: datetime64[ns]
    

    也可以很简便地转换时区:

    In [274]: stz = s.dt.tz_localize('US/Eastern')
    
    In [275]: stz
    Out[275]: 
    0   2013-01-01 09:10:12-05:00
    1   2013-01-02 09:10:12-05:00
    2   2013-01-03 09:10:12-05:00
    3   2013-01-04 09:10:12-05:00
    dtype: datetime64[ns, US/Eastern]
    
    In [276]: stz.dt.tz
    Out[276]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
    

    你还可以连续做这些类型的操作:

    In [277]: s.dt.tz_localize('UTC').dt.tz_convert('US/Eastern')
    Out[277]: 
    0   2013-01-01 04:10:12-05:00
    1   2013-01-02 04:10:12-05:00
    2   2013-01-03 04:10:12-05:00
    3   2013-01-04 04:10:12-05:00
    dtype: datetime64[ns, US/Eastern]
    

    你也可以利用Series.dt.strftime()将日期值转化为字符串,这也同样支持标准的strftime()语法。

    # DatetimeIndex
    In [278]: s = pd.Series(pd.date_range('20130101', periods=4))
    
    In [279]: s
    Out[279]: 
    0   2013-01-01
    1   2013-01-02
    2   2013-01-03
    3   2013-01-04
    dtype: datetime64[ns]
    
    In [280]: s.dt.strftime('%Y/%m/%d')
    Out[280]: 
    0    2013/01/01
    1    2013/01/02
    2    2013/01/03
    3    2013/01/04
    dtype: object
    
    # PeriodIndex
    In [281]: s = pd.Series(pd.period_range('20130101', periods=4))
    
    In [282]: s
    Out[282]: 
    0    2013-01-01
    1    2013-01-02
    2    2013-01-03
    3    2013-01-04
    dtype: period[D]
    
    In [283]: s.dt.strftime('%Y/%m/%d')
    Out[283]: 
    0    2013/01/01
    1    2013/01/02
    2    2013/01/03
    3    2013/01/04
    dtype: object
    

    .dt访问器可用于Period和TimeDelta数据类型。

    # period
    In [284]: s = pd.Series(pd.period_range('20130101', periods=4, freq='D'))
    
    In [285]: s
    Out[285]: 
    0    2013-01-01
    1    2013-01-02
    2    2013-01-03
    3    2013-01-04
    dtype: period[D]
    
    In [286]: s.dt.year
    Out[286]: 
    0    2013
    1    2013
    2    2013
    3    2013
    dtype: int64
    
    In [287]: s.dt.day
    Out[287]: 
    0    1
    1    2
    2    3
    3    4
    dtype: int64
    
    # timedelta
    In [288]: s = pd.Series(pd.timedelta_range('1 day 00:00:05', periods=4, freq='s'))
    
    In [289]: s
    Out[289]: 
    0   1 days 00:00:05
    1   1 days 00:00:06
    2   1 days 00:00:07
    3   1 days 00:00:08
    dtype: timedelta64[ns]
    
    In [290]: s.dt.days
    Out[290]: 
    0    1
    1    1
    2    1
    3    1
    dtype: int64
    
    In [291]: s.dt.seconds
    Out[291]: 
    0    5
    1    6
    2    7
    3    8
    dtype: int64
    
    In [292]: s.dt.components
    Out[292]: 
       days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
    0     1      0        0        5             0             0            0
    1     1      0        0        6             0             0            0
    2     1      0        0        7             0             0            0
    3     1      0        0        8             0             0            0
    

    *注意: 如果你对非日期的值使用Series.dt,将会报错。

    3.3.10 矢量化字符串方法

    Series自带一套字符串处理方法,可以很方便地对数组中的每个元素进行操作。可能最重要的是,这些方法不包括对缺失值(即NA值)的自动处理。这些方法可以通过Series的str属性访问到,而且方法名字和python字符串内置的方法的名字是一致的。比如:

    In [293]: s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
    
    In [294]: s.str.lower()
    Out[294]: 
    0       a
    1       b
    2       c
    3    aaba
    4    baca
    5     NaN
    6    caba
    7     dog
    8     cat
    dtype: object
    

    pandas也提供了强大的模式匹配功能,但是请注意模式匹配默认使用正则表达式(在一些情况下,正则表达式是常用的)。
    完整的描述请看矢量化字符串方法

    相关文章

      网友评论

        本文标题:pandas0.24.1文档3.3 基础功能(二)

        本文链接:https://www.haomeiwen.com/subject/lcdbvqtx.html