我的数据以多索引数据帧组织。我正试图通过" Sweep"索引并返回特定时间范围内的最小值(或最大值)以及该时间发生的时间。
数据如下:
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()的输出(即峰值)传递给返回值,这些值会出现在时间中吗?
答案 0 :(得分: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])
然后你可以写一个非常简单的变换函数,它将返回每组数据(按扫描索引分组),最小值为&#39; Primary&#39;位于。这可以用简单的布尔切片来完成。这看起来像这样:
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()
函数为该组编制索引。我尝试使用transform进行此操作,但它只是返回整个数据帧。我不确定为什么会这样,但它确实适用于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
- 也许有人会启发我们。
答案 1 :(得分:1)
我不知道这是否适用于您的多索引框架,但值得一试;使用:
>>> 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