数据框的复杂掩码
Complex mask for dataframe
我有一个数据框,其中一个列包含一个时间序列。数据看起来像这个图表
我想创建一个每次数据等于或小于 -0.20 时都为 TRUE 的掩码。它也应该是 TRUE before 达到 -0.20 而为负。 after 达到 -0.20 也应该是 true 为负。
本版图
是我手动尝试显示(红色)掩码为 TRUE 的值。我开始创建掩码,但我只能在数据小于 -0.20 mask = (df['data'] < -0.2)
时使其等于 TRUE。我不能做得更好了,有人知道如何实现我的目标吗?
想法
按相同符号的连续值分组,然后检查这样一组的最小值是否小于定义的阈值。
实施
首先,我们要将负值与正值分开。
negative_mask = (df['data']<0)
然后我们可以为每个连续的正序列或负序列创建 classes(以整数排序)。每次数据改变符号时,class 加一。
consecutives = negative_mask.diff().ne(0).cumsum()
然后我们select只取连续元素组中最小值小于0.2的数据
df.groupby(consecutives).filter(lambda df : df[0].min() < -0.2)
随机数据示例
我们可以用随机数据试试我们的例子:
import numpy as np
import pandas as pd
np.random.seed(42)
data = np.random.randint(-300, 300, size=1000)/1000
df = pd.DataFrame(data, columns=["data"])
输出
data
2 -0.030
3 -0.194
4 -0.229
5 -0.280
6 -0.179
... ...
991 -0.293
995 -0.247
996 -0.062
997 -0.072
999 -0.250
363 rows × 1 columns
一种方法是将完全低于零的段分组,然后针对每个组验证是否有任何值低于 -0.2
。
请参阅下面的完整可重现示例脚本:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
np.random.seed(167)
df = pd.DataFrame(
{"y": np.cumsum([np.random.uniform(-0.01, 0.01) for _ in range(10 ** 5)])}
)
plt.plot(df)
gt_zero = df["y"] < 0
regions = (gt_zero != gt_zero.shift()).cumsum()
# here's your interesting DataFrame with the specified mask
df_interesting = df.groupby(regions).filter(lambda s: s.min() < -0.2)
# plot individual regions
for i, grp in df.groupby(regions):
if grp["y"].min() < -0.2:
plt.plot(grp, color="tab:red", linewidth=5, alpha=0.6)
plt.axhline(0, linestyle="--", color="tab:gray")
plt.axhline(-0.2, linestyle="--", color="tab:gray")
plt.show()
我有一个数据框,其中一个列包含一个时间序列。数据看起来像这个图表
我想创建一个每次数据等于或小于 -0.20 时都为 TRUE 的掩码。它也应该是 TRUE before 达到 -0.20 而为负。 after 达到 -0.20 也应该是 true 为负。 本版图
是我手动尝试显示(红色)掩码为 TRUE 的值。我开始创建掩码,但我只能在数据小于 -0.20 mask = (df['data'] < -0.2)
时使其等于 TRUE。我不能做得更好了,有人知道如何实现我的目标吗?
想法
按相同符号的连续值分组,然后检查这样一组的最小值是否小于定义的阈值。
实施
首先,我们要将负值与正值分开。
negative_mask = (df['data']<0)
然后我们可以为每个连续的正序列或负序列创建 classes(以整数排序)。每次数据改变符号时,class 加一。
consecutives = negative_mask.diff().ne(0).cumsum()
然后我们select只取连续元素组中最小值小于0.2的数据
df.groupby(consecutives).filter(lambda df : df[0].min() < -0.2)
随机数据示例
我们可以用随机数据试试我们的例子:
import numpy as np
import pandas as pd
np.random.seed(42)
data = np.random.randint(-300, 300, size=1000)/1000
df = pd.DataFrame(data, columns=["data"])
输出
data
2 -0.030
3 -0.194
4 -0.229
5 -0.280
6 -0.179
... ...
991 -0.293
995 -0.247
996 -0.062
997 -0.072
999 -0.250
363 rows × 1 columns
一种方法是将完全低于零的段分组,然后针对每个组验证是否有任何值低于 -0.2
。
请参阅下面的完整可重现示例脚本:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
np.random.seed(167)
df = pd.DataFrame(
{"y": np.cumsum([np.random.uniform(-0.01, 0.01) for _ in range(10 ** 5)])}
)
plt.plot(df)
gt_zero = df["y"] < 0
regions = (gt_zero != gt_zero.shift()).cumsum()
# here's your interesting DataFrame with the specified mask
df_interesting = df.groupby(regions).filter(lambda s: s.min() < -0.2)
# plot individual regions
for i, grp in df.groupby(regions):
if grp["y"].min() < -0.2:
plt.plot(grp, color="tab:red", linewidth=5, alpha=0.6)
plt.axhline(0, linestyle="--", color="tab:gray")
plt.axhline(-0.2, linestyle="--", color="tab:gray")
plt.show()