我试图遍历Pyspark数据框的所有列,计算IQR以过滤上部异常值,并重新分配相同的数据帧。有200多列。这是有效的,但随着它在循环中前进,它会越来越慢。我怀疑问题可能在于重新分配数据帧(dfBufferOutlier = dfBufferOutlier.filter(col(i)
nameList=dfBuffer.schema.names[1:]
dfBufferOutlier=dfBuffer
for i in nameList:
cuenta=dfBufferOutlier.filter(col(i)>0).count()
if cuenta>0:
Q1, Q2, Q3 = dfBufferOutlier.filter(col(i)>0).approxQuantile(col=i,probabilities=[0.25,0.5,0.75],relativeError=0.005)
IQR=(Q3-Q1)
top_limit=Q3+1.5*IQR
dfBufferOutlier=dfBufferOutlier.filter(col(i)<top_limit)
肯定有另一种方法可以让它变得更好,但无法弄清楚......有什么帮助吗?
答案 0 :(得分:1)
如果你愿意修改程序(可以说你应该修改它),你可以在一次通过中完成所有工作:
from pyspark.sql.functions import col, count, when
from functools import reduce
from operator import and_
def iqr_filter(df, cols, relativeError=0.005):
# Find quantiles
quantiles = (df
# Convert values <= 0 to NULL
.select([when(col(c) > 0, col(c)).alias(c) for c in cols])
.approxQuantile(cols, [0.25, 0.5, 0.75], relativeError))
# Compute thresholds
thresholds = [
q3 + 1.5 * (q3 - q1) for q1, _, q3 in quantiles
]
# Create SQL expression of form c1 < t1 AND c2 < t2 AND ... AND cn < tn
expr = reduce(and_, [col(c) < t for c, t in zip(cols, thresholds)])
# Filter
return df.where(expr)
用法:
iqr_filter(dfBuffer, dfBuffer.schema.names[1:])
由于相对误差非常小,它可能仍然是非常苛刻的工作,所以我强烈建议稍微放松一下,一旦列数增加。
请注意,结果将与您当前方法生成的结果不同: