Pandas中文官档~基础用法3

mac2024-12-15  14

呆鸟云:“觉得有用,就请点个在看,哈哈”

函数应用

不管是为 pandas 对象应用自定义函数,还是应用其它第三方函数,都离不开以下三种方法。用哪种方法取决于操作的对象是 DataFrame 或 Series ,是行或列,还是元素。 表级函数应用:`pipe()` 行列级函数应用: apply() 聚合 API:`agg()` 与 `transform()` 元素级函数应用:`applymap()`

表级函数应用

虽然可以把   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 当作首位参数。要是想把数据作为第二个参数,该怎么办?本例中, pipe 为元组 ( callable,data_keyword)形式。 .pipe 把   DataFrame  作为元组里指定的参数。 下例用 statsmodels 拟合回归。该 API 先接收一个公式, DataFrame 是第二个参数, data。要传递函数,则要用 pipe 接收关键词对 ( sm.ols,'data')。 In [ 138]:  import statsmodels.formula.api  as sm In [ 139]: bb = pd.read_csv( 'data/baseball.csv', index_col= 'id') In [ 140]: (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[ 140]:  < class 'statsmodels.iolib.summary.Summary'>"""                            OLS Regression Results                            ==============================================================================DepVariable:                     hr   R-squared:                        0.685 Model:                            OLS   Adj. R-squared:                   0.665 Method:                 Least Squares   F-statistic:                      34.28 Date:                Thu,  22 Aug  2019   Prob (F-statistic):            3.48e-15 Time:                         15: 48: 59   Log-Likelihood:                 -205.92 No. Observations:                   68   AIC:                              421.8 Df Residuals:                       63   BIC:                              432.9 Df 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.780 C(lg)[T.NL]     -2.2736       1.325      -1.716       0.091       -4.922        0.375 ln_h            -1.3542       0.875      -1.547       0.127       -3.103        0.395 year             4.2277       2.324       1.819       0.074       -0.417        8.872 g                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.298 Skew:                            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 are strong multicollinearity  or other numerical problems. unix 的 pipe  与后来出现的 dplyr 及 magrittr 启发了 pipe 方法,在此,引入了 R 语言里用于读取 pipe 的操作符 ( %>%)。 pipe 的实现思路非常清晰,仿佛 Python 源生的一样。强烈建议大家阅读   pipe()  的源代码。

行列级函数应用

apply() 方法可以沿着 DataFrame 的轴应用任何函数,比如,描述性统计方法,该方法支持   axis 参数。 In [ 141]: df.apply(np.mean) Out[ 141]:  one       0.811094 two       1.360588 three     0.187958 dtype: float64 In [ 142]: df.apply(np.mean, axis= 1) Out[ 142]:  a     1.583749 b     0.734929 c     1.133683 d    -0.166914 dtype: float64 In [ 143]: df.apply( lambda x: x.max() - x.min()) Out[ 143]:  one       1.051928 two       1.632779 three     1.840607 dtype: float64 In [ 144]: df.apply(np.cumsum) Out[ 144]:          one       two     three a   1.394981   1.772517       NaN b   1.738035   3.684640  -0.050390 c   2.433281   5.163008   1.177045 d       NaN   5.442353   0.563873 In [ 145]: df.apply(np.exp) Out[ 145]:          one       two     three a   4.034899   5.885648       NaN b   1.409244   6.767440   0.950858 c   2.004201   4.385785   3.412466 d       NaN   1.322262   0.541630 apply() 方法还支持通过函数名字符串调用函数。 In [ 146]: df.apply( 'mean') Out[ 146]:  one       0.811094 two       1.360588 three     0.187958 dtype: float64 In [ 147]: df.apply( 'mean', axis= 1) Out[ 147]:  a     1.583749 b     0.734929 c     1.133683 d    -0.166914 dtype: float64 默认情况下, apply() 调用的函数返回的类型会影响 DataFrame.apply 输出结果的类型。 函数返回的是 Series 时,最终输出的结果是 DataFrame。输出的列与函数返回的 Series 索引相匹配。 函数返回其它任意类型时,输出结果是 Series。 result_type  会覆盖默认行为,该参数有三个选项: reduce、 broadcast、 expand。这些选项决定了列表型返回值是否扩展为 DataFrame。 用好 apply() 可以了解数据集的很多信息。比如可以提取每列的最大值对应的日期: In [ 148]: tsdf = pd.DataFrame(np.random.randn( 10003), columns=[ 'A''B''C'],    .....:                     index=pd.date_range( '1/1/2000', periods= 1000))    .....:  In [ 149]: tsdf.apply( lambda x: x.idxmax()) Out[ 149]:  A    2000 -08 -06 B    2001 -01 -18 C    2001 -07 -18 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 方法的功能也很实用: In [ 150]: tsdf Out[ 150]:                     A         B         C 2000 -01 -01  -0.158131  -0.232466   0.321604 2000 -01 -02  -1.810340  -3.105758   0.433834 2000 -01 -03  -1.209847  -1.156793  -0.136794 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.653602   0.178875   1.008298 2000 -01 -09   1.007996   0.462824   0.254472 2000 -01 -10   0.307473   0.600337   1.643950 In [ 151]: tsdf.apply(pd.Series.interpolate) Out[ 151]:                     A         B         C 2000 -01 -01  -0.158131  -0.232466   0.321604 2000 -01 -02  -1.810340  -3.105758   0.433834 2000 -01 -03  -1.209847  -1.156793  -0.136794 2000 -01 -04  -1.098598  -0.889659   0.092225 2000 -01 -05  -0.987349  -0.622526   0.321243 2000 -01 -06  -0.876100  -0.355392   0.550262 2000 -01 -07  -0.764851  -0.088259   0.779280 2000 -01 -08  -0.653602   0.178875   1.008298 2000 -01 -09   1.007996   0.462824   0.254472 2000 -01 -10   0.307473   0.600337   1.643950 apply() 有一个参数 raw,默认值为 False,在应用函数前,使用该参数可以将每行或列转换为 Series。该参数为 True 时,传递的函数接收 ndarray 对象,若不需要索引功能,这种操作能显著提高性能。

聚合 API

0.20.0 版新增。 聚合 API 可以快速、简洁地执行多个聚合操作。Pandas 对象支持多个类似的 API,如 groupby API、window functions API、resample API。聚合函数为 DataFrame.aggregate(),它的别名是 DataFrame.agg()。 这里使用与前例类似的 DataFrame: In [ 152]: tsdf = pd.DataFrame(np.random.randn( 103), columns=[ 'A''B''C'],    .....:                     index=pd.date_range( '1/1/2000', periods= 10))    .....:  In [ 153]: tsdf.iloc[ 3: 7] = np.nan In [ 154]: tsdf Out[ 154]:                     A         B         C 2000 -01 -01   1.257606   1.004194   0.167574 2000 -01 -02  -0.749892   0.288112  -0.757304 2000 -01 -03  -0.207550  -0.298599   0.116018 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.814347  -0.257623   0.869226 2000 -01 -09  -0.250663  -1.206601   0.896839 2000 -01 -10   2.169758  -1.333363   0.283157 应用单个函数时,该操作与 apply() 等效,这里也可以用字符串表示聚合函数名。下面的聚合函数输出的结果为 Series: In [ 155]: tsdf.agg(np.sum) Out[ 155]:  A     3.033606 B    -1.803879 C     1.575510 dtype: float64 In [ 156]: tsdf.agg( 'sum') Out[ 156]:  A     3.033606 B    -1.803879 C     1.575510 dtype: float64 # 因为应用的是单个函数,该操作与`.sum()` 是等效的 In [ 157]: tsdf.sum() Out[ 157]:  A     3.033606 B    -1.803879 C     1.575510 dtype: float64 对 Series 进行单个聚合操作,返回的是标量值: In [ 158]: tsdf.A.agg( 'sum') Out[ 158]:  3.033606102414146

多函数聚合

还可以用列表形式传递多个聚合函数。每个函数在输出结果 DataFrame 里以行的形式显示,行名是每个聚合函数的函数名。 In [ 159]: tsdf.agg([ 'sum']) Out[ 159]:              A         B        C sum   3.033606  -1.803879   1.57551 多个函数输出多行: In [ 160]: tsdf.agg([ 'sum''mean']) Out[ 160]:               A         B         C sum    3.033606  -1.803879   1.575510 mean   0.505601  -0.300647   0.262585 对于 Series,多个函数返回的结果也是 Series,其索引为函数名: In [ 161]: tsdf.A.agg([ 'sum''mean']) Out[ 161]:  sum      3.033606 mean     0.505601 Name: A, dtype: float64 传递 lambda 函数时,输出名为 <lambda> 的行: In [ 162]: tsdf.A.agg([ 'sum'lambda x: x.mean()]) Out[ 162]:  sum          3.033606 < lambda>     0.505601 Name: A, dtype: float64 应用自定义函数时,则该函数名为输出结果的行名: In [ 163]:  def mymean(x):    .....:      return x.mean()    .....:  In [ 164]: tsdf.A.agg([ 'sum', mymean]) Out[ 164]:  sum        3.033606 mymean     0.505601 Name: A, dtype: float64

用字典实现聚合

指定为哪些列应用哪些聚合函数时,需要把包含列名与标量(或标量列表)的字典传递给 DataFrame.agg。 注意:这里输出结果的顺序不是固定的,要想让输出顺序与输入顺序一致,请使用 OrderedDict。 In [ 165]: tsdf.agg({ 'A''mean''B''sum'}) Out[ 165]:  A     0.505601 B    -1.803879 dtype: float64 输入的参数是列表时,输出结果为   DataFrame,并以矩阵形式显示所有聚合函数的计算结果,且输出结果由所有唯一函数组成。未执行聚合操作的列输出结果为 NaN 值: In [ 166]: tsdf.agg({ 'A': [ 'mean''min'],  'B''sum'}) Out[ 166]:               A         B mean   0.505601       NaN min   -0.749892       NaN sum        NaN  -1.803879

多种 Dtype

DataFrame 里包含不能执行聚合操作的多种 Dtype 时, .agg 只计算可以执行聚合的列。这与 groupby 的 .agg 操作类似: In [ 167]: mdf = pd.DataFrame({ 'A': [ 123],    .....:                      'B': [ 1.2.3.],    .....:                      'C': [ 'foo''bar''baz'],    .....:                      'D': pd.date_range( '20130101', periods= 3)})    .....:  In [ 168]: mdf.dtypes Out[ 168]:  A             int64 B           float64 C            object D    datetime64[ns] dtype: object In [ 169]: mdf.agg([ 'min''sum']) Out[ 169]:       A    B          C          D min   1   1.0        bar  2013 -01 -01 sum   6   6.0  foobarbaz        NaT

自定义 Describe

用 .agg() 可以轻松地创建与内置 describe 函数类似的自定义 describe 函数。 In [ 170]:  from functools  import partial In [ 171]: q_25 = partial(pd.Series.quantile, q= 0.25) In [ 172]: q_25.__name__ =  '25%' In [ 173]: q_75 = partial(pd.Series.quantile, q= 0.75) In [ 174]: q_75.__name__ =  '75%' In [ 175]: tsdf.agg([ 'count''mean''std''min', q_25,  'median', q_75,  'max']) Out[ 175]:                 A         B         C count    6.000000   6.000000   6.000000 mean     0.505601  -0.300647   0.262585 std      1.103362   0.887508   0.606860 min     -0.749892  -1.333363  -0.757304 25%     -0.239885  -0.979600   0.128907 median   0.303398  -0.278111   0.225365 75%      1.146791   0.151678   0.722709 max      2.169758   1.004194   0.896839

Transform API

0.20.0 版新增。 transform() 方法返回的结果与原始数据具有同样索引,且大小相同。这个 API 支持同时处理多种操作,不用一个一个操作,且该 API 与 .agg API 类似。 下面先创建一个 DataFrame: In [ 176]: tsdf = pd.DataFrame(np.random.randn( 103), columns=[ 'A''B''C'],    .....:                     index=pd.date_range( '1/1/2000', periods= 10))    .....:  In [ 177]: tsdf.iloc[ 3: 7] = np.nan In [ 178]: tsdf Out[ 178]:                     A         B         C 2000 -01 -01  -0.428759  -0.864890  -0.675341 2000 -01 -02  -0.168731   1.338144  -1.279321 2000 -01 -03  -1.621034   0.438107   0.903794 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.254374  -1.240447  -0.201052 2000 -01 -09  -0.157795   0.791197  -1.144209 2000 -01 -10  -0.030876   0.371900   0.061932 这里转换的是整个 DataFrame。 .transform() 支持 Numpy 函数、字符串函数及自定义函数。 In [ 179]: tsdf.transform(np.abs) Out[ 179]:                     A         B         C 2000 -01 -01   0.428759   0.864890   0.675341 2000 -01 -02   0.168731   1.338144   1.279321 2000 -01 -03   1.621034   0.438107   0.903794 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.254374   1.240447   0.201052 2000 -01 -09   0.157795   0.791197   1.144209 2000 -01 -10   0.030876   0.371900   0.061932 In [ 180]: tsdf.transform( 'abs') Out[ 180]:                     A         B         C 2000 -01 -01   0.428759   0.864890   0.675341 2000 -01 -02   0.168731   1.338144   1.279321 2000 -01 -03   1.621034   0.438107   0.903794 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.254374   1.240447   0.201052 2000 -01 -09   0.157795   0.791197   1.144209 2000 -01 -10   0.030876   0.371900   0.061932 In [ 181]: tsdf.transform( lambda x: x.abs()) Out[ 181]:                     A         B         C 2000 -01 -01   0.428759   0.864890   0.675341 2000 -01 -02   0.168731   1.338144   1.279321 2000 -01 -03   1.621034   0.438107   0.903794 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.254374   1.240447   0.201052 2000 -01 -09   0.157795   0.791197   1.144209 2000 -01 -10   0.030876   0.371900   0.061932 这里的 transform() 接受单个函数;与 ufunc 等效。 In [ 182]: np.abs(tsdf) Out[ 182]:                     A         B         C 2000 -01 -01   0.428759   0.864890   0.675341 2000 -01 -02   0.168731   1.338144   1.279321 2000 -01 -03   1.621034   0.438107   0.903794 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.254374   1.240447   0.201052 2000 -01 -09   0.157795   0.791197   1.144209 2000 -01 -10   0.030876   0.371900   0.061932 .transform() 向 Series 传递单个函数时,返回的结果也是单个 Series。 In [ 183]: tsdf.A.transform(np.abs) Out[ 183]:  2000 -01 -01     0.428759 2000 -01 -02     0.168731 2000 -01 -03     1.621034 2000 -01 -04         NaN 2000 -01 -05         NaN 2000 -01 -06         NaN 2000 -01 -07         NaN 2000 -01 -08     0.254374 2000 -01 -09     0.157795 2000 -01 -10     0.030876 Freq: D, Name: A, dtype: float64

多函数 Transform

transform() 调用多个函数时,将生成多重索引 DataFrame。第一层是原始数据集的列名;第二层是 transform() 调用的函数名。 In [ 184]: tsdf.transform([np.abs,  lambda x: x +  1]) Out[ 184]:                     A                   B                   C                       absolute  < lambda>  absolute  < lambda>  absolute  < lambda> 2000 -01 -01   0.428759   0.571241   0.864890   0.135110   0.675341   0.324659 2000 -01 -02   0.168731   0.831269   1.338144   2.338144   1.279321  -0.279321 2000 -01 -03   1.621034  -0.621034   0.438107   1.438107   0.903794   1.903794 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.254374   1.254374   1.240447  -0.240447   0.201052   0.798948 2000 -01 -09   0.157795   0.842205   0.791197   1.791197   1.144209  -0.144209 2000 -01 -10   0.030876   0.969124   0.371900   1.371900   0.061932   1.061932 为 Series 应用多个函数时,输出结果是 DataFrame,列名是 transform() 调用的函数名。 In [ 185]: tsdf.A.transform([np.abs,  lambda x: x +  1]) Out[ 185]:              absolute  < lambda> 2000 -01 -01   0.428759   0.571241 2000 -01 -02   0.168731   0.831269 2000 -01 -03   1.621034  -0.621034 2000 -01 -04       NaN       NaN 2000 -01 -05       NaN       NaN 2000 -01 -06       NaN       NaN 2000 -01 -07       NaN       NaN 2000 -01 -08   0.254374   1.254374 2000 -01 -09   0.157795   0.842205 2000 -01 -10   0.030876   0.969124

用字典执行 `transform` 操作

函数字典可以为每列执行指定 transform() 操作。 In [ 186]: tsdf.transform({ 'A': np.abs,  'B'lambda x: x +  1}) Out[ 186]:                     A         B 2000 -01 -01   0.428759   0.135110 2000 -01 -02   0.168731   2.338144 2000 -01 -03   1.621034   1.438107 2000 -01 -04       NaN       NaN 2000 -01 -05       NaN       NaN 2000 -01 -06       NaN       NaN 2000 -01 -07       NaN       NaN 2000 -01 -08   0.254374  -0.240447 2000 -01 -09   0.157795   1.791197 2000 -01 -10   0.030876   1.371900 transform() 的参数是列表字典时,生成的是以 transform() 调用的函数为名的多重索引 DataFrame。 In [ 187]: tsdf.transform({ 'A': np.abs,  'B': [ lambda x: x +  1'sqrt']}) Out[ 187]:                     A         B                       absolute  < lambda>      sqrt 2000 -01 -01   0.428759   0.135110       NaN 2000 -01 -02   0.168731   2.338144   1.156782 2000 -01 -03   1.621034   1.438107   0.661897 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.254374  -0.240447       NaN 2000 -01 -09   0.157795   1.791197   0.889493 2000 -01 -10   0.030876   1.371900   0.609836

元素级函数应用

并非所有函数都能矢量化,即接受 Numpy 数组,返回另一个数组或值,DataFrame 的 applymap() 及 Series 的 map() ,支持任何接收单个值并返回单个值的 Python 函数。 示例如下: In [ 188]: df4 Out[ 188]:          one       two     three a   1.394981   1.772517       NaN b   0.343054   1.912123  -0.050390 c   0.695246   1.478369   1.227435 d       NaN   0.279344  -0.613172 In [ 189]:  def f(x):    .....:      return len(str(x))    .....:  In [ 190]: df4[ 'one'].map(f) Out[ 190]:  a     18 b     19 c     18 d      3 Name: one, dtype: int64 In [ 191]: df4.applymap(f) Out[ 191]:     one  two  three a    18    17       3 b    19    18      20 c    18    18      16 d     3    19      19 Series.map() 还有个功能,可以“连接”或“映射”第二个 Series 定义的值。这与 merging/joining 功能联系非常紧密: In [ 192]: s = pd.Series([ 'six''seven''six''seven''six'],    .....:               index=[ 'a''b''c''d''e'])    .....:  In [ 193]: t = pd.Series({ 'six'6.'seven'7.}) In [ 194]: s Out[ 194]:  a      six b    seven c      six d    seven e      six dtype: object In [ 195]: s.map(t) Out[ 195]:  a     6.0 b     7.0 c     6.0 d     7.0 e     6.0 dtype: float64

精选好文:

最新回复(0)