【问题标题】:pandas groupby - return min() along with time where min() occurspandas groupby - 返回 min() 以及 min() 发生的时间
【发布时间】:2023-04-04 16:40:02
【问题描述】:

我的数据组织在多索引数据框中。我正在尝试按“扫描”索引进行分组,并返回特定时间范围内的最小值(或最大值)以及该时间发生的时间。

数据如下:

             Time       Primary  Secondary    BL LED
Sweep                                               
Sweep1 0  0.00000 -28173.828125  -0.416565 -0.000305
       1  0.00005 -27050.781250  -0.416260  0.000305
       2  0.00010 -27490.234375  -0.415955 -0.002441
       3  0.00015 -28222.656250  -0.416260  0.000305
       4  0.00020 -28759.765625  -0.414429 -0.002136

获取最小值或最大值非常简单。

def find_groupby_peak(voltage_df, start_time, end_time, peak="min"):
    boolean_vr = (voltage_df.Time >= start_time) & (voltage_df.Time <=end_time)
    df_subset = voltage_df[boolean_vr]
    grouped = df_subset.groupby(level="Sweep")
    if peak == "min":
        peak = grouped.Primary.min()
    elif peak == "max":
        peak = grouped.max()

    return peak

给出(部分输出):

Sweep
Sweep1    -92333.984375
Sweep10   -86523.437500
Sweep11   -85205.078125
Sweep12   -87109.375000
Sweep13   -77929.687500

但我也需要确定这些峰值出现的时间。我知道我可以遍历输出并找到这些值在原始数据集中出现的位置,但这似乎是一种相当蛮力的方法。我还可以编写一个不同的函数来应用于返回最大值和出现最大值的时间的分组对象(至少在理论上 - 没有尝试过这样做,但我认为这很简单)。

除了这两个选项之外,是否有更简单的方法来传递来自 grouped.Primary.min() 的输出(即峰值)以返回这些值出现的时间?

【问题讨论】:

    标签: python pandas group-by min


    【解决方案1】:

    您可以考虑将变换函数与 groupby 一起使用。如果您的数据看起来有点像这样:

    import pandas as pd
    sweep =     ["sweep1", "sweep1", "sweep1", "sweep1", 
                "sweep2", "sweep2", "sweep2", "sweep2",
                "sweep3", "sweep3", "sweep3", "sweep3",
                "sweep4", "sweep4", "sweep4", "sweep4"]
    Time =      [0.009845, 0.002186,  0.006001,  0.00265,  
                0.003832,  0.005627,  0.002625,  0.004159,  
                0.00388,  0.008107,  0.00813,  0.004813, 
                0.003205,  0.003225,  0.00413,  0.001202]
    Primary =   [-2832.013203,  -2478.839133,  -2100.671551,  -2057.188346,  
                 -2605.402055,  -2030.195497,  -2300.209967,  -2504.817095,  
                 -2865.320903,  -2456.0049,  -2542.132906,  -2405.657053,  
                 -2780.140743,  -2351.743053,  -2232.340363,  -2820.27356]
    s_count =   [ 0, 1, 2, 3,
                  0, 1, 2, 3,
                  0, 1, 2, 3,
                  0, 1, 2, 3]
    
    df = pd.DataFrame({ 'Time'      : Time,
                        'Primary'   : Primary}, index = [sweep, s_count])
    

    然后您可以编写一个非常简单的转换函数,该函数将为每组数据(按扫描索引分组)返回“Primary”最小值所在的行。这可以通过简单的布尔切片来完成。看起来像这样:

    def trans_function(df):
        return df[df.Primary == min(df.Primary)]
    

    然后要使用这个函数,只需在 transform 方法中调用它:

    df.groupby(level = 0).transform(trans_function)
    

    这给了我以下输出:

                  Primary      Time
    sweep1 0 -2832.013203  0.009845
    sweep2 0 -2605.402055  0.003832
    sweep3 0 -2865.320903  0.003880
    sweep4 3 -2820.273560  0.001202
    

    如果你需要的话,显然你可以将它合并到你的函数中,该函数作用于数据的某个子集。

    作为替代方法,您可以使用argmin() 函数为组编制索引。我试图用转换来做到这一点,但它只是返回整个数据框。我不确定为什么会这样,但它确实适用于apply

    def trans_function2(df):
        return df.loc[df['Primary'].argmin()]
    
    df.groupby(level = 0).apply(trans_function2)
    

    这又给了我:

                Primary      Time
    sweep1 -2832.013203  0.009845
    sweep2 -2605.402055  0.003832
    sweep3 -2865.320903  0.003880
    sweep4 -2820.273560  0.001202
    

    我不完全确定为什么此功能不适用于transform - 也许有人会启发我们。

    【讨论】:

    • 您的第一个解决方案(trans_function + transform)完美运行。将不得不阅读有关 groupby 转换的更多内容以了解那里发生了什么。谢谢!
    • 在我看来,transformapply 函数非常不透明,文档也没有太大帮助。然而,一旦你掌握了它们,它们就会非常有用。
    • 是的,只是快速阅读有关转换的文档我还是有点困惑。不过刚刚开始,所以我已经习惯了处于轻度混乱的永久状态;)
    【解决方案2】:

    我不知道这是否适用于您的多索引框架,但值得一试;合作:

    >>> df
      tag       tick  val
    z   C 2014-09-07   32
    y   C 2014-09-08   67
    x   A 2014-09-09   49
    w   A 2014-09-10   80
    v   B 2014-09-11   51
    u   B 2014-09-12   25
    t   C 2014-09-13   22
    s   B 2014-09-14    8
    r   A 2014-09-15   76
    q   C 2014-09-16    4
    

    使用idxmax 找到索引器,然后使用.loc

    >>> i = df.groupby('tag')['val'].idxmax()
    >>> df.loc[i]
      tag       tick  val
    w   A 2014-09-10   80
    v   B 2014-09-11   51
    y   C 2014-09-08   67
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      • 2019-04-10
      • 2022-12-02
      • 2012-10-29
      • 2017-06-21
      相关资源
      最近更新 更多