在 Pandas 中学习使用地图

Learning to use map in Pandas

我想为两个数据框列 df1 和 df2 逐行建模此 excel 公式:

=IF(df1 > df2; df2; df2 - df1)

我知道这可以通过 Python 中的 map 来完成,但不知道如何实现。我可以使用 for 循环和 if-else 语句来完成它,但这会使我的代码更难阅读。

你能帮帮我吗?

这实际上是 maskwhere 的工作。

df2.mask(df1 <= df2, df2 - df1)

或者,

df2.where(df1 > df2, df2 - df1)

更一般地说,这是来自 numpy:

np.where(df1 > df2, df2, df2 - df1)

对于这些示例数据帧:

df1
Out: 
          A         B         C
0  0.446762 -0.435975  0.109038
1 -0.729108  3.670354  0.761667
2 -0.244370 -0.256956 -1.831161

df2
Out: 
          A         B         C
0 -1.192108  0.074628 -0.087634
1 -0.324098  0.698479 -0.287896
2  1.807863 -2.564992 -2.361296

前两个收益率

          A         B         C
0 -1.192108  0.510603 -0.087634
1  0.405010  0.698479 -0.287896
2  2.052233 -2.564992 -2.361296

np.where returns 一个 numpy 数组,因此您可能需要将其转换回 DataFrame:

array([[-1.19210755,  0.51060284, -0.08763422],
       [ 0.40500973,  0.69847936, -0.28789618],
       [ 2.05223294, -2.56499239, -2.36129577]])

我想你的意思是创建一个新列,它是列 df1df2 的函数,按照你描述的方式。 (如果我错了,请纠正我。)

那么这是一个使用apply函数的案例,使用pandas你应该熟悉一下。假设您的数据框称为 df,您的新列将称为 df3。那么:

df3 = df.apply(lambda x : x["df2"] if x["df1"] > x["df2"] else x["df2"] - x["df1"], axis=1)

这里发生了很多事情,特别是因为你是 applying to the whole DataFrame (usually you see apply used with just one column as input - technically, apply to a Series - 而且语法更简单。)需要 axis=1 向 pandas 解释这应该应用于列集(您可能认为这是默认设置,但事实并非如此,因此在应用于整个 DataFrame 时请始终记住使用它。)lambda 用于访问两列并执行功能;在这里,x 是抽象的 DataFrame 本身的任何行。基本上,这是一种进行矢量化映射的方法。它是 pandas 中最常用的工具之一,您会发现自己经常使用它。

一个很好的基础 apply 教程是 here, showing mostly applications to a single column (with the simpler syntax I mentioned, where you don't need axis=1.) Here also 是另一个应用于多列的示例。

这可以通过

实现
df2 - df1*(df2 > df1)

例如,

In [51]: df1
Out[51]: 
0    0.588922
1    0.876270
2    0.276917
3    0.521514
dtype: float64

In [52]: df2
Out[52]: 
0    0.628234
1    0.492461
2    0.782199
3    0.759758
dtype: float64

In [53]: df2 - df1*(df2 > df1)
Out[53]: 
0    0.039312
1    0.492461
2    0.505282
3    0.238245
dtype: float64

在性能方面,目前发布的三个解决方案在 (100000, 2) 形 DataFrame 上的表现如下:

In [124]: df = pd.DataFrame()

In [125]: df['df1'] = np.random.uniform(size=10**5)

In [126]: df['df2'] = np.random.uniform(size=10**5)

In [127]: df1 = df.df1

In [128]: df2 = df.df2

In [130]: %timeit df.apply(lambda x : x["df2"] if x["df1"] > x["df2"] else x["df2"] - x["df1"], axis=1)
1 loop, best of 3: 8.97 s per loop

In [131]: %timeit df2.where(df1 > df2, df2 - df1)
100 loops, best of 3: 3.57 ms per loop

In [132]: %timeit df2 - df1*(df2 > df1)
1000 loops, best of 3: 1.61 ms per loop