检测 pandas 中值变化较小的 DataFrame 列中的异常值
Detecting outliers in a DataFrame column with small value changes in pandas
我正在处理一个列,该列的值在行之间应该有微小的变化。这些值是物理测量值,由于环境因素,测量值可能不正确,连续样本之间的增量非常高。变化率是一个被视为问题输入的数量,因为它可以改变以适应这种异常值检测的精度需求。
检测方法可以计算到目前为止所见值的平均值,并将离群值标记为高于其给定变化率的值,或者检查行之间的值变化并标记索引值,其中距离大于变化率和指数值,其中值 returned 低于可接受的变化率,相对于标记为异常值之前的第一个值。第一种方法可能更难,因为平均值应该根据正确的值计算,也就是说,标记为异常值的值不应被考虑到平均值的计算中。
正确的解决方案应该是 return 指示异常值的索引列表,然后将其用于将相应的值设置为 f.e。 NaN
或使用插值方法填充这些值。
例子
df = pd.DataFrame({'small_changing': [5.14, 5.18, 5.22, 5.18, 5.20, 5.17, 5.25, 5.55, 5.62, 5.78, 6.21, 6.13, 5.71, 5.35, 5.29, 5.24, 5.16, 5.18, 5.20, 5.15, 5.17, 5.00, 4.96, 4.88, 4.71, 4.65, 4.73, 4.79, 4.89, 4.92, 5.05, 5.11, 5.14, 5.17, 5.22, 5.24, 5.18, 5.20]})
假设变化率为0.15
,假设第二种检测方法考虑了行之间的差异,则有两个异常值组需要检测。
第一组对应索引值[7, 12]
,因为行6
和7
相差0.3
,高于0.15
限制,6
和 13
行之间的差异是 0.1
,第 13
行是差异在 0.15
限制内的第一行.
第二组对应索引值[21, 29]
,因为行20
和21
相差0.17
,高于0.15
限制,20
和 30
行之间的差异是 0.12
,第 30
行是差异在 0.15
限制内的第一行.
此示例的结果:[7, 8, 9, 10, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29]
希望对您有所帮助。
我认为它不是 pythonic,但它有效:
def outlier_detection(points, limit):
outliers_index = list()
k=0
for i in range(0,len(points)-1):
if abs(points[i-k] - points[i+1]) >= limit:
k+=1
outliers_index.append(i+1)
else:
k=0
return outliers_index
outlier_detection(df['small_changing'].values, 0.15)
OUT: [7, 8, 9, 10, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29]
这可能会节省处理大数据集上稀疏分布异常值的时间 -
def df_outlier(df, threshold=0.15):
column = df.columns[0]
df["outlier"] = False
df_difference = df.copy()
df_difference["difference"] = abs(df[column] - df[column].shift(1)).shift(-1)
df_difference = df_difference.loc[df_difference["difference"] > threshold]
for index in df_difference.index:
row = df.loc[index]
if not row["outlier"]:
df_check = df[index+1:].copy()
df_check["a_difference"] = abs(df_check[column] - row[column])
df_check.loc[df_check["a_difference"] > threshold, "outlier"] = True
df.loc[((df.index >= df_check.index[0]) & (df.index < df_check["outlier"].ne(True).idxmax())), "outlier"] = True
return list(df.loc[df["outlier"] == True].index)
我正在使用这个。
我正在处理一个列,该列的值在行之间应该有微小的变化。这些值是物理测量值,由于环境因素,测量值可能不正确,连续样本之间的增量非常高。变化率是一个被视为问题输入的数量,因为它可以改变以适应这种异常值检测的精度需求。
检测方法可以计算到目前为止所见值的平均值,并将离群值标记为高于其给定变化率的值,或者检查行之间的值变化并标记索引值,其中距离大于变化率和指数值,其中值 returned 低于可接受的变化率,相对于标记为异常值之前的第一个值。第一种方法可能更难,因为平均值应该根据正确的值计算,也就是说,标记为异常值的值不应被考虑到平均值的计算中。
正确的解决方案应该是 return 指示异常值的索引列表,然后将其用于将相应的值设置为 f.e。 NaN
或使用插值方法填充这些值。
例子
df = pd.DataFrame({'small_changing': [5.14, 5.18, 5.22, 5.18, 5.20, 5.17, 5.25, 5.55, 5.62, 5.78, 6.21, 6.13, 5.71, 5.35, 5.29, 5.24, 5.16, 5.18, 5.20, 5.15, 5.17, 5.00, 4.96, 4.88, 4.71, 4.65, 4.73, 4.79, 4.89, 4.92, 5.05, 5.11, 5.14, 5.17, 5.22, 5.24, 5.18, 5.20]})
假设变化率为0.15
,假设第二种检测方法考虑了行之间的差异,则有两个异常值组需要检测。
第一组对应索引值[7, 12]
,因为行6
和7
相差0.3
,高于0.15
限制,6
和 13
行之间的差异是 0.1
,第 13
行是差异在 0.15
限制内的第一行.
第二组对应索引值[21, 29]
,因为行20
和21
相差0.17
,高于0.15
限制,20
和 30
行之间的差异是 0.12
,第 30
行是差异在 0.15
限制内的第一行.
此示例的结果:[7, 8, 9, 10, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29]
希望对您有所帮助。
我认为它不是 pythonic,但它有效:
def outlier_detection(points, limit):
outliers_index = list()
k=0
for i in range(0,len(points)-1):
if abs(points[i-k] - points[i+1]) >= limit:
k+=1
outliers_index.append(i+1)
else:
k=0
return outliers_index
outlier_detection(df['small_changing'].values, 0.15)
OUT: [7, 8, 9, 10, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29]
这可能会节省处理大数据集上稀疏分布异常值的时间 -
def df_outlier(df, threshold=0.15):
column = df.columns[0]
df["outlier"] = False
df_difference = df.copy()
df_difference["difference"] = abs(df[column] - df[column].shift(1)).shift(-1)
df_difference = df_difference.loc[df_difference["difference"] > threshold]
for index in df_difference.index:
row = df.loc[index]
if not row["outlier"]:
df_check = df[index+1:].copy()
df_check["a_difference"] = abs(df_check[column] - row[column])
df_check.loc[df_check["a_difference"] > threshold, "outlier"] = True
df.loc[((df.index >= df_check.index[0]) & (df.index < df_check["outlier"].ne(True).idxmax())), "outlier"] = True
return list(df.loc[df["outlier"] == True].index)
我正在使用这个。