简介
在pandas中, apply() 方法使用是非常灵活的,他比 agg() 方法使用更自由。数据分析师日常使用最多的就是 apply() 方法了,而与之类似的还有 applymap() 和 map() 方法,因此本文将详细介绍下这三种方法的使用和区别:
- apply:应用在DataFrame的行或列中;
- applymap:应用在DataFrame的每个元素中;
- map:应用在单独一列(Series)的每个元素中。
知道它们的使用范围那就好办,接下来我们将会一一做介绍。
apply()方法
前面也说了apply方法是一般性的“拆分-应用-合并”方法。它既可以得到一个经过广播的标量值,也可以得到一个相同大小的结果数组。我们先来看下函数形式:
1 |
DataFrame.apply(func, axis=0, broadcast=None, raw=False, reduce=None, result_type=None, args=(), **kwds) |
最重要的是传入的参数 func , func 可以是已经有的函数(比如: np.mean )或者自定义的函数。假设现有如下数据:
1 2 3 4 5 6 7 8 |
>>>import numpy as np >>>import pandas as pd >>>df = pd.DataFrame(np.random.randn(2, 2), columns=list('AB')) >>>df A B 0 0.109197 0.510993 1 0.888893 0.561702 |
可以直接使用NumPy的函数:
1 2 3 4 5 6 7 8 9 10 11 |
# 默认为行运算 >>>df.apply(np.sum) A 0.998090 B 1.072696 dtype: float64 # axis=1列运算 >>>df.apply(np.sum, axis=1) 0 0.620191 1 1.450596 dtype: float64 |
或者使用 lambda 函数做简单的运算:
1 2 3 4 |
>>>df.apply(lambda x: x + 1) A B 0 1.109197 1.510993 1 1.888893 1.561702 |
但是这样使用起来非常不方便,每次都要定义 lambda 函数。因此可以通过 def 定义一个函数,然后再调用该函数,在实际处理中都是定义自己所需要的函数完成操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
>>>def cal_result(df, x, y): df['C'] = (df['A'] + df['B']) * x df['D'] = (df['A'] + df['B']) * y return df >>>df.apply(cal_result, x=3, y=8, axis=1) # 第一种方式 A B C D 0 0.109197 0.510993 1.860572 4.961525 1 0.888893 0.561702 4.351787 11.604764 >>>df.apply(cal_result, args=(3, 8), axis=1) # 第二种方式 A B C D 0 0.109197 0.510993 1.860572 4.961525 1 0.888893 0.561702 4.351787 11.604764 >>>df.apply(cal_result, **{'x': 3, 'y': 8}, axis=1) # 第三种方式 A B C D 0 0.109197 0.510993 1.860572 4.961525 1 0.888893 0.561702 4.351787 11.604764 |
在这里我们先定义了一个 cal_result 函数,它的作用是计算 A,B 列和的 x 倍和 y 倍添加到 C,D 列中。这里有三种方式可以完成参数的赋值,第一种方式直接通过关键字参数赋值,指定参数的值;第二种方式是使用 args 关键字参数传入一个包含参数的元组;第三种方式传入通过 ** 传入包含参数和值的字典。
apply的使用是很灵活的,再举一个例子,配合 loc 方法我们能够在最后一行得到一个总和:
1 2 3 4 5 6 |
>>>df.loc[2] = df.apply(np.sum) >>>df A B 0 0.109197 0.510993 1 0.888893 0.561702 2 0.998090 1.072696 |
applymap()方法
该方法针对DataFrame中的元素进行操作,还是使用这个数据:
1 2 3 4 5 |
>>>df A B 0 0.109197 0.510993 1 0.888893 0.561702 2 0.998090 1.072696 |
此时我们想保留2位小数,可以这样实现:
1 2 3 4 5 |
>>>df.applymap(lambda x: '%.2f'%x) A B 0 0.11 0.51 1 0.89 0.56 2 1.00 1.07 |
在这里可以看到applymap方法操作的是其中的元素,并且是对整个DataFrame进行了格式化,我们也可以选择行或列中的元素:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 取列 >>>df[['A']].applymap(lambda x: '%.2f'%x) A 0 0.11 1 0.89 2 1.00 # 取行 >>>pd.DataFrame(df.loc[2]).applymap(lambda x: '%.2f'%x) 2 A 1.00 B 1.07 |
需要注意的是这里必须使用 df[['A']] ,表示这是一个DataFrame,而不是一个Series,如果使用 df['A'] 就会报错。同样从行取元素也要将它先转成DataFrame。还需要注意apply方法和applymap的区别:
- apply方法操作的是行或列的运算,而不是元素的运算,比如在这里使用格式化操作就会报错;
- applymap方法操作的是元素,因此没有诸如axis这样的参数,它只接受函数传入。
map()方法
如果你对applymap方法搞清楚了,那么map方法就很简单,说白了map方法是应用在Series中的,还是举上面的例子:
1 2 3 4 5 6 7 8 9 10 11 |
>>>df[['A']].applymap(lambda x: '%.2f'%x) A 0 0.11 1 0.89 2 1.00 >>>df['A'].map(lambda x: '%.2f'%x) 0 0.11 1 0.89 2 1.00 Name: A, dtype: object |
applymap是DataFrame的方法,而map是Series方法。
总结
本文详细介绍了apply、applymap、map方法的使用和区别。再次强调:
- apply:应用在DataFrame的行或列中;
- applymap:应用在DataFrame的每个元素中;
- map:应用在单独一列(Series)的每个元素中。
在数据分析过程中,使用自定义函数能够将繁琐的操作串联起来,提高工作效率。因此对这几个函数要熟练掌握,以后才能事半功倍。