Pandas DataFrame.Apply输出格式

3

关于在Python的pandas.DataFrame中使用apply()方法的输出有疑问?

Q1 -

当apply函数返回与输入的形状相同的数组时,为什么该函数会返回一个格式与输入的pandas.DataFrame相同的pandas.DataFrame?

例如

foo = pd.DataFrame([[1,2],[3,4]],columns=['a','b'])
foo.apply(lambda x: [np.min(x)/2,np.max(x)/2], axis='index') 

代码将返回:
       a        b   
0   min(a)/2   min(b)/2  
1   max(a)/2   max(b)/2 

Q2 -

由于某些原因,我想输出一个数组的 pandaq.Series

0   [min(a)/2, max(a)/2]  
1   [min(b)/2, max(b)/2]
...

我尝试使用 reduce=True,但没有成功。 那么,我该怎么办呢?

先行致谢。

2个回答

1
我更倾向于在可以使用 numpy 操作时避免使用 apply
在这种情况下,至少有几个替代方案。以下是一些带基准测试的示例。如您所见,越接近 numpy,结果就越好。
import pandas as pd, numpy as np

foo = pd.DataFrame([[1,2],[3,4]],columns=['a','b'])

foo = pd.concat([foo]*10000, ignore_index=True)

def dark(df):
    return df.apply(lambda x: tuple([np.min(x)/2,np.max(x)/2]), axis=1)

def jp1(df):
    return [tuple([np.min(x)/2,np.max(x)/2]) for x in foo[['a', 'b']].values]

def jp2(df):
    arr = foo[['a', 'b']].values
    return list(zip(*(np.min(arr, axis=1)/2, np.max(arr, axis=1)/2)))

%timeit dark(foo)  # 4.95s
%timeit jp1(foo)   # 298ms
%timeit jp2(foo)   # 4.68ms

当然,dark()返回一个pd.Series,但是pandas允许你通过列表进行赋值。

1
因为结果数组的 ndim 为 2。如果您查看 apply 的主代码 here,如果 ndim 为 2,则应用 DataFrame 构造函数。
    #Main Code
    ...
    # TODO: mixed type case
    if result.ndim == 2:
        return DataFrame(result, index=self.index, columns=self.columns)
    else:
        return Series(result, index=self._get_agg_axis(axis))

如果您想要结果作为一系列,那么请使用类似于tuple的东西,而不是列表,即
foo = pd.DataFrame([[1,2],[3,4]],columns=['a','b'])
foo.apply(lambda x: tuple([np.min(x)/2,np.max(x)/2]), axis=1)

输出:

0    (0.5, 1.0)
1    (1.5, 2.0)
dtype: object

希望它有所帮助。

非常感谢您的回答,使用元组而不是数组可以解决问题。 - David Leon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接