主要问题当然是您如何定义“巨大差异”。您的解决方案很好地获得了最大的差异,仅通过使用 .diff(-1) 和使用 Jezrael 所示的绝对值来改进:
differences = df['A'].diff(-1).abs()
如果您的值未排序,则使用绝对值很重要,在这种情况下,您可能会得到负差异。
然后,您可能应该对这些值进行一些聚类,并获得具有最大值的集群的最小索引。 Jezrael 已经通过使用最大的四分位数展示了启发式方法,但是仅稍微修改您的示例就行不通了:
df = pd.DataFrame({'A': [1, 1.05, 1.2, 1.3, 1.4, 1.5, 7, 7.1, 7.2, 15, 15.1]})
differences = df['A'].diff(-1).abs()
idx = differences.index[differences >= differences.quantile(.75)][0]
print(idx, differences[idx])
这会返回1 0.1499999999999999
这里还有 3 个可能更适合您的启发式方法:
-
如果您有一个高于该值的值,您认为差异“很大”(例如1.5):
idx = differences.index[differences >= 1.5][0]
-
如果你知道有多少个大值,你可以选择那些并得到最小的索引(例如2):
idx = differences.nlargest(2).index.min()
-
如果您知道所有小值都分组在一起(如示例中的所有 0.1),您可以过滤大于均值的值(或者如果您的“大”值非常接近较小的)。
idx = differences.index[differences >= differences.mean()][0]
这是因为与中位数相反,您的少数较大差异会显着提高均值。
如果您真的想进行适当的聚类,可以使用 scikit learn 中的 KMeans 算法:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2).fit(differences.values[:-1].reshape(-1, 1))
clusters = pd.Series(kmeans.labels_, index=differences.index[:-1])
idx = clusters.index[clusters.eq(np.squeeze(kmeans.cluster_centers_).argmax())][0]
这会将数据分为 2 类,然后将分类放入 pandas Series。然后我们通过只选择具有最高值的集群来过滤这个系列的索引,最后得到这个过滤索引的第一个元素。