微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

查找曲线下的最大面积|熊猫,matplotlib

如何解决查找曲线下的最大面积|熊猫,matplotlib

在这方面有些挣扎-为了找到必要的电池容量,我需要分析一年的数据来分析生产/需求。为此,我认为我需要计算0线以下的最大面积。我想我需要找到该区域的起点/终点并将其各自的y值乘以所有值?

这是我的图表的简化版本:

enter image description here

这是图像中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)

解决方法

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

'

Sample data

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

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

使用pandas groupby计算所有面积并找到最大的负数

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

Largest Area under 0-line

这是如何工作的

我创建了一个易于遵循的数据集

df = pd.DataFrame({
    'value': x[1:],'border': x1
})
dfg = df.groupby('border')
mingr = dfg.apply(lambda x: np.trapz(x.value)).idxmin()
plt.plot(x[1:])
plt.plot(
    dfg.get_group(mingr).value
);
plt.title(
    "position from {} to {}".format(
        dfg.get_group(mingr).index[0],dfg.get_group(mingr).index[-1]));

Dataset

我想知道具有连续负值或正值的序列。可以使用过滤器X

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--');

现在,当我比较每个连续值时,我可以找到符号改变的索引。我在数据前加上一个False,以不丢失第一个值。

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

对于df['sign_switch'] = np.diff(np.r_[False,X < 0]) df[:10] value lt_zero sign_switch 0 3.125986 False False 1 3.885588 False False 2 4.580410 False False 3 2.998920 False False 4 1.913088 False False 5 -2.902447 True True 6 -3.986654 True False 7 -4.373026 True False 8 -2.878661 True False 9 -1.929964 True False ,我为每个序列得到一个递增的整数值。现在,每个序列都有一个分组变量。

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

您以后可以访问每个组并使用区域。例如绘制区域。

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

Plot with Areas

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。