DataFrame的apply函数是对指定的轴进行循环处理,并返回处理的结果。这里有一个问题在于,如果对于每一次运算,返回的结果只有一个元素,那么最终得到的结果是一个Series;但是如果每次处理返回的不是一个元素,而是由单个或者多个元素组成的可迭代对象,比如列表,那么最终得到的是Series还是DataFrame呢?对此,可以使用apply函数的result_type参数来指定。
result_type参数可以取'reduce','expand','broadcast'以及None,默认是None。
reduce表示最终返回一个Seies,expand表示返回一个DataFrame,但是该DataFrame的columns(axis=1时,如果axis=0,则同样的类推)会被重新以从0开始的整数设定(如果是list-like对象,不是Series),原columns会被抛弃,所以expand下每次处理的返回结果的可迭代对象长度不一定要和原来的列数匹配,如果每次处理返回的是一个Series,那么被expand得到的最终的DataFrame的列名和Series的index是一致的。
broadcast表示的是维持原来的列名不变(当然三个参数类型的index都不会变),所以这就要求每次处返回的结果的对象长度要和原来的列数一致,不然会报错。
如果是None,则pandas会根据每次处理返回的结果类型自己判断,如果每次处理返回的是list-like的对象,则和reduce一样,但是如果每次处理返回的是一个Series,则和expand一样。
最后要注意的是,result_type参数是在每次处理返回的对象是可迭代的才有意义,如果只是一个元素的话,那么最终得到的都是Series,result_type参数便没有意义了。还有resuly_type参数是在pandas0.23.0版本开始加入的,在该版本之前,分别有broadcast参数和reduce参数来分别设定,但是没有expand参数以及相应的功能。
示例代码:
import pandas as pd
import numpy as np
df=pd.DataFrame(np.arange(12).reshape(4,3),columns=['a','b','c'])
df.index=['d','e','f','g']
print(df)
[Out]:
a b c
d 0 1 2
e 3 4 5
f 6 7 8
g 9 10 11
#默认的None下,如果是list-like对象,则最终返回Series
df.apply(lambda x:[1,2,3],axis=1)
[Out]:
d [1, 2, 3]
e [1, 2, 3]
f [1, 2, 3]
g [1, 2, 3]
dtype: object
#默认的None下,如果每次返回的是Series对象,则最终expand成DataFrame
df.apply(lambda x:pd.Series([1,2,3],index=['a','b','d']),axis=1)
[Out]:
a b d
d 1 2 3
e 1 2 3
f 1 2 3
g 1 2 3
#expand下,得到DataFrame,如果是list-like对象,列索引设为整数
df.apply(lambda x:[1,2,3],result_type='expand',axis=1)
[Out]:
0 1 2
d 1 2 3
e 1 2 3
f 1 2 3
g 1 2 3
#broadcast下,保持原DataFrame的列名不变,返回DataFrame,如果其中的[1,2,3]长度不为3,比如为[1,2],那么由于长度不匹配,便会报错
df.apply(lambda x:[1,2,3],result_type='broadcast',axis=1)
[Out]:
a b c
d 1 2 3
e 1 2 3
f 1 2 3
g 1 2 3