【问题标题】:Comparing a column's value with an array (or a series) of decreasing size将列的值与大小递减的数组(或一系列)进行比较
【发布时间】:2017-11-17 18:33:16
【问题描述】:

我有以下数据框。 (这不一定是数据框;numpy 数组 df.values 的解决方案也足够了)

np.random.seed(42)
df = pd.DataFrame(np.random.random((10,2)),columns=['a', 'b'])
df

        a           b
0   0.374540    0.950714
1   0.731994    0.598658
2   0.156019    0.155995
3   0.058084    0.866176
4   0.601115    0.708073
5   0.020584    0.969910
6   0.832443    0.212339
7   0.181825    0.183405
8   0.304242    0.524756
9   0.431945    0.291229

我想包含一个具有以下逻辑值的新列:

真:如果某个特定 a 值之后的任何 b 值大于该部分 a 假:否则

预期的输出是: (请参阅下面一些行的解释)

       a           b      c
0   0.374540    0.950714  True
1   0.731994    0.598658  True
2   0.156019    0.155995  True
3   0.058084    0.866176  True   <- np.any(0.058084 < np.array([0.708073, 0.969910, 0.212339, 0.183405, 0.524756, 0.291229]))
4   0.601115    0.708073  True   <- np.any(0.601115 < np.array([0.969910, 0.212339, 0.183405, 0.524756, 0.291229]))
5   0.020584    0.969910  True   <- np.any(0.020584 < np.array([0.212339, 0.183405, 0.524756, 0.291229]))
6   0.832443    0.212339  False  <- np.any(0.832443 < np.array([0.183405, 0.524756, 0.291229]))
7   0.181825    0.183405  True   <- np.any(0.181825 < np.array([0.524756, 0.291229]))
8   0.304242    0.524756  False  <- np.any(0.304242  < np.array([0.291229]))
9   0.431945    0.291229  UNDEFINED <- Ignore this

使用 for 循环应该可以实现上述操作,但是 pandas/numpy 的方法是什么?

我正在尝试一种方法,将 lambda 函数应用于a,但我找不到一种方法来获取相应a 值的索引来进行np.any 比较,如上所示。 (我后来发现apply 只是 for 循环的语法糖)

df['c'] = df['a'].apply(lambda x: np.any(x < df['b'].values[<i>:])) # Where <i> is the respective index value of x; which I didn't know how to find

【问题讨论】:

    标签: python pandas numpy vectorization


    【解决方案1】:

    诀窍是在b 上自下而上查找累积的最大值并将其与a 中的相应值进行比较。

    因此,实现将是 -

    a = df.a.values
    b = df.b.values
    out = a[:-1] < np.maximum.accumulate(b[::-1])[::-1][1:]
    

    移植到pandas,对应的将是df.cummax for np.maximum.accumulate

    示例运行 -

    In [45]: df
    Out[45]: 
              a         b
    0  0.374540  0.950714
    1  0.731994  0.598658
    2  0.156019  0.155995
    3  0.058084  0.866176
    4  0.601115  0.708073
    5  0.020584  0.969910
    6  0.832443  0.212339
    7  0.181825  0.183405
    8  0.304242  0.524756
    9  0.431945  0.291229
    
    In [46]: out
    Out[46]: array([ True,  True,  True,  True,  True,  True, False,  True, False], dtype=bool)
    

    【讨论】:

      【解决方案2】:

      为了补充@Divakar 的答案,使用cummax() 的熊猫方法将是:

      df['c'] = df['a'] < df['b'][::-1].cummax()[::-1].reset_index(drop=True).shift(-1)
      
      print(df)  
      
              a         b      c
      0  0.374540  0.950714   True
      1  0.731994  0.598658   True
      2  0.156019  0.155995   True
      3  0.058084  0.866176   True
      4  0.601115  0.708073   True
      5  0.020584  0.969910   True
      6  0.832443  0.212339  False
      7  0.181825  0.183405   True
      8  0.304242  0.524756  False
      9  0.431945  0.291229  False
      

      【讨论】:

      • 那里可能需要换班:df['a'].shift(1)?
      • 谢谢@Divakar!我错过了。添加了df['b'][::-1].cummax()[::-1].reset_index(drop=True).shift(-1)。我认为我们不能在这里转移df['a']
      猜你喜欢
      • 2019-04-08
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多