gpt4 book ai didi

python-3.x - pyspark中的异常值检测

转载 作者:行者123 更新时间:2023-12-01 10:21:00 25 4
gpt4 key购买 nike

我有一个 pyspark 数据框,如下所示。

+---+-------+--------+
|age|balance|duration|
+---+-------+--------+
| 2| 2143| 261|
| 44| 29| 151|
| 33| 2| 76|
| 50| 1506| 92|
| 33| 1| 198|
| 35| 231| 139|
| 28| 447| 217|
| 2| 2| 380|
| 58| 121| 50|
| 43| 693| 55|
| 41| 270| 222|
| 50| 390| 137|
| 53| 6| 517|
| 58| 71| 71|
| 57| 162| 174|
| 40| 229| 353|
| 45| 13| 98|
| 57| 52| 38|
| 3| 0| 219|
| 4| 0| 54|
+---+-------+--------+

我的预期输出应该是这样的,
+---+-------+--------+-------+-----------+------------+
|age|balance|duration|age_out|balance_out|duration_out|
+---+-------+--------+-------+-----------+------------+
| 2| 2143| 261| 1| 1| 0|
| 44| 29| 151| 0| 0| 0|
| 33| 2| 76| 0| 0| 0|
| 50| 1506| 92| 0| 1| 0|
| 33| 1| 198| 0| 0| 0|
| 35| 231| 139| 0| 0| 0|
| 28| 447| 217| 0| 0| 0|
| 2| 2| 380| 1| 0| 0|
| 58| 121| 50| 0| 0| 0|
| 43| 693| 55| 0| 0| 0|
| 41| 270| 222| 0| 0| 0|
| 50| 390| 137| 0| 0| 0|
| 53| 6| 517| 0| 0| 1|
| 58| 71| 71| 0| 0| 0|
| 57| 162| 174| 0| 0| 0|
| 40| 229| 353| 0| 0| 0|
| 45| 13| 98| 0| 0| 0|
| 57| 52| 38| 0| 0| 0|
| 3| 0| 219| 1| 0| 0|
| 4| 0| 54| 0| 0| 0|
+---+-------+--------+-------+-----------+------------+

在这里,我的目标是通过使用四分位间距方法来识别数据集中的异常记录,如下面的 Python 代码中所述。如果我们发现任何异常记录,那么我们需要将它们标记为 1,否则标记为 0。

我可以通过使用下面的代码使用 python 做同样的事情。
import numpy as np
def outliers_iqr(ys):
quartile_1, quartile_3 = np.percentile(ys, [25, 75])
iqr = quartile_3 - quartile_1
lower_bound = quartile_1 - (iqr * 1.5)
upper_bound = quartile_3 + (iqr * 1.5)
ser = np.zeros(len(ys))
pos =np.where((ys > upper_bound) | (ys < lower_bound))[0]
ser[pos]=1
return(ser)

但我想在 pyspark 中做同样的事情。有人可以帮助我吗?

我的pyspark代码:
def outliers_iqr(ys):
quartile_1, quartile_3 = np.percentile(ys, [25, 75])
iqr = quartile_3 - quartile_1
lower_bound = quartile_1 - (iqr * 1.5)
upper_bound = quartile_3 + (iqr * 1.5)
ser = np.zeros(len(ys))
pos =np.where((ys > upper_bound) | (ys < lower_bound))[0]
ser[pos]=1
return(float(ser))

outliers_iqr_udf = udf(outliers_iqr, FloatType())
DF.withColumn('age_out', outliers_iqr_udf(DF.select('age').collect())).show()

最佳答案

You can use pyspark.sql.DataFrame.approxQuantile 在循环内为每个列获取所需的第 25 个和第 75 个百分位值。

bounds = {
c: dict(
zip(["q1", "q3"], df.approxQuantile(c, [0.25, 0.75], 0))
)
for c in df.columns
}

传递的最后一个参数是相对误差,您可以在链接的帖子以及 docs 上阅读相关信息。 .简而言之,数字越小,您的结果就越准确,但在准确性和计算成本之间需要权衡。 (这里我使用 0 来获取确切值,但您可能希望根据数据大小选择不同的值。)

获得第一个和第三个四分位数值后,您可以计算 iqr和上/下界很容易:

for c in bounds:
iqr = bounds[c]['q3'] - bounds[c]['q1']
bounds[c]['lower'] = bounds[c]['q1'] - (iqr * 1.5)
bounds[c]['upper'] = bounds[c]['q3'] + (iqr * 1.5)
print(bounds)
#{'age': {'lower': 3.0, 'q1': 33.0, 'q3': 53.0, 'upper': 83.0},
# 'balance': {'lower': -570.0, 'q1': 6.0, 'q3': 390.0, 'upper': 966.0},
# 'duration': {'lower': -143.0, 'q1': 76.0, 'q3': 222.0, 'upper': 441.0}}

现在使用 pyspark.sql.functions.when在基于 bounds 构建离群值列的列表理解中:

import pyspark.sql.functions as f
df.select(
"*",
*[
f.when(
f.col(c).between(bounds[c]['lower'], bounds[c]['upper']),
0
).otherwise(1).alias(c+"_out")
for c in df.columns
]
).show()
#+---+-------+--------+-------+-----------+------------+
#|age|balance|duration|age_out|balance_out|duration_out|
#+---+-------+--------+-------+-----------+------------+
#| 2| 2143| 261| 1| 1| 0|
#| 44| 29| 151| 0| 0| 0|
#| 33| 2| 76| 0| 0| 0|
#| 50| 1506| 92| 0| 1| 0|
#| 33| 1| 198| 0| 0| 0|
#| 35| 231| 139| 0| 0| 0|
#| 28| 447| 217| 0| 0| 0|
#| 2| 2| 380| 1| 0| 0|
#| 58| 121| 50| 0| 0| 0|
#| 43| 693| 55| 0| 0| 0|
#| 41| 270| 222| 0| 0| 0|
#| 50| 390| 137| 0| 0| 0|
#| 53| 6| 517| 0| 0| 1|
#| 58| 71| 71| 0| 0| 0|
#| 57| 162| 174| 0| 0| 0|
#| 40| 229| 353| 0| 0| 0|
#| 45| 13| 98| 0| 0| 0|
#| 57| 52| 38| 0| 0| 0|
#| 3| 0| 219| 0| 0| 0|
#| 4| 0| 54| 0| 0| 0|
#+---+-------+--------+-------+-----------+------------+

这里我用了 between检查值是否不是异常值,并且此函数是包含性的(即 x between a and b 在逻辑上等同于 x >= a and x <= b )。

关于python-3.x - pyspark中的异常值检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52633916/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com