Python 寻找曲线下的最大面积| pandas,matplotlib

Python 寻找曲线下的最大面积| pandas,matplotlib,python,pandas,matplotlib,area,Python,Pandas,Matplotlib,Area,我在这方面有点挣扎——为了找到必要的电池容量,我需要分析一年的生产/需求数据。为此,我想我需要计算0线下的最大面积。我想我需要找到该区域的起点/终点,然后将所有的值乘以相应的y值 这是我的图表的一个缩略版本: 这是图像中0下的最大区域,但在完整数据集中,它可以是任何区域。我知道如何在我找到问题区域边界的情况下整合它,但我正在努力找到一种有效的方法来做到这一点 我的数据框如下所示: demand Production diff Time 2019-

我在这方面有点挣扎——为了找到必要的电池容量,我需要分析一年的生产/需求数据。为此,我想我需要计算0线下的最大面积。我想我需要找到该区域的起点/终点,然后将所有的值乘以相应的y值

这是我的图表的一个缩略版本: 这是图像中0下的最大区域,但在完整数据集中,它可以是任何区域。我知道如何在我找到问题区域边界的情况下整合它,但我正在努力找到一种有效的方法来做到这一点

我的数据框如下所示:

                     demand  Production    diff
Time
2019-01-01 00:15:01   17.25      32.907  15.657
2019-01-01 00:30:01   17.80      32.954  15.154
...                     ...         ...     ...
2019-01-16 22:15:02   17.34      27.704  10.364
2019-01-16 22:30:01   18.67      35.494  16.824
我使用这个片段来查找最长区域的时间步长长度,但是如果有办法将点乘以它们的y值(diff),我就找不到了。这在技术上是不正确的,但是,考虑到一个区域可能长但窄,而另一个区域可能短且高,因此整体面积更大

def max0(sr):
     return (sr >= 0).cumsum().value_counts().max() - (0 if (sr >= 0).cumsum().value_counts().idxmax() < 0 else 1)
def max0(sr):
返回(sr>=0).cumsum().value_counts().max()-(如果(sr>=0).cumsum().value_counts().idxmax()<0,则返回0

您可以在0线下找到最大的区域。 我生成了自己的数据

x = np.random.randn(100000)
x = x.cumsum()-x.mean()
plt.plot(x);

现在计算正序列和负序列的起点和终点。序列中的每个值都会得到一个递增的整数,以便能够按序列分组

x1 = np.diff(x < 0).cumsum()

df['sign_sequence'] = np.diff(np.r_[False, X < 0]).cumsum()
df[:10]
      value  lt_zero  sign_switch  sign_sequence
0  3.125986    False        False              0
1  3.885588    False        False              0
2  4.580410    False        False              0
3  2.998920    False        False              0
4  1.913088    False        False              0
5 -2.902447     True         True              1
6 -3.986654     True        False              1
7 -4.373026     True        False              1
8 -2.878661     True        False              1
9 -1.929964     True        False              1

这是怎么回事 我创建了一个更易于跟踪的数据集

x = np.array([3,4,4.5,3,2])
X = np.r_[x,-x,x,-x]+np.random.normal(0,.2,20)
plt.figure(figsize=(12,5))
plt.axhline(0, color='gray')
plt.plot(X, 'o--');

我想知道连续负值或正值的序列。这可以通过过滤器X<0进行存档

df = pd.DataFrame({'value': X, 'lt_zero': X < 0})
df[:10]
      value  lt_zero
0  3.125986    False
1  3.885588    False
2  4.580410    False
3  2.998920    False
4  1.913088    False
5 -2.902447     True
6 -3.986654     True
7 -4.373026     True
8 -2.878661     True
9 -1.929964     True
对于每个组,我可以计算组中值的积分

sign_groups = df.groupby('sign_sequence')
sign_groups.apply(lambda x: np.trapz(x.value))
sign_sequence
0    13.984455
1   -13.654547
2    14.370044
3   -14.549090
您可以稍后访问每个组并使用这些区域。例如,绘制区域

plt.figure(figsize=(12,5))
plt.plot(X,'o--')
plt.axhline(0, c='gray')
for e,group in enumerate(sign_groups):
    plt.fill_between(group[1].index,0, group[1].value)
    area = np.trapz(group[1].value)
    plt.text((e)*5+1.5, np.sign(area) * 1.25, f'{area:.2f}', fontsize=12)

这是否回答了您的问题?不完全是,否:(这是曲线下最大(包括高度)的面积还是最长的面积(仅x坐标)?我看到你在0线下按经度分组,用np.trapz()计算面积,然后应用lambda函数查找数据中的最高负片区域。好的,直到这里。在我的例子中,打印mingr返回1。不知怎的,这与dfg.get_组(mingr)有关.value是否…起作用?我想得到面积最小的组?如果你能详细阐述一下这一步的原理,我会非常感激。:)还有,有没有可能把最大面积变成一个变量,这样我就可以对它进行进一步的计算?@eddieevt:我添加了一个简单数据的例子。以及如何使用计算面积的示例(此处为绘图)。我希望很清楚如何得到变量中的面积。对于最大和最小面积,您可以使用
np.min()
np.max()
。非常感谢,您是一个宝藏!:)
sign_groups = df.groupby('sign_sequence')
sign_groups.apply(lambda x: np.trapz(x.value))
sign_sequence
0    13.984455
1   -13.654547
2    14.370044
3   -14.549090
plt.figure(figsize=(12,5))
plt.plot(X,'o--')
plt.axhline(0, c='gray')
for e,group in enumerate(sign_groups):
    plt.fill_between(group[1].index,0, group[1].value)
    area = np.trapz(group[1].value)
    plt.text((e)*5+1.5, np.sign(area) * 1.25, f'{area:.2f}', fontsize=12)