Python:将平均值设置为异常值

时间:2017-05-17 13:43:35

标签: python pandas numpy

我有数据框

ID  Value
A   70
A   80
A   1000
A   100
A   200
A   130
A   60
A   300
A   800
A   200
A   150
A   250

我需要将异常值替换为中值。 我用

df = pd.read_excel("test.xlsx")
grouped = df.groupby('ID')
statBefore = pd.DataFrame({'q1': grouped['Value'].quantile(.25), \
'median': grouped['Value'].median(), 'q3' : 
grouped['Value'].quantile(.75)})
def is_outlier(row):
    iq_range = statBefore.loc[row.ID]['q3'] - statBefore.loc[row.ID]['q1']
    median = statBefore.loc[row.ID]['median']
    q3 = statBefore.loc[row.ID]['q3']
    q1 = statBefore.loc[row.ID]['q1']
    if row.Value > (q3 + (3 * iq_range)) or row.Value < (q1 - (3 * iq_range)):
        return True
    else:
        return False
#apply the function to the original df:
df.loc[:, 'outlier'] = df.apply(is_outlier, axis = 1)

但是它会返回中位数 - 175和q1 - 92,但我得到 - 90,它会返回q3 - 262,5,但我算得上 - 275。 那有什么不对?

2 个答案:

答案 0 :(得分:0)

这很简单,性能很好,没有Python for循环来降低速度:

s = pd.Series([30, 31, 32, 45, 50, 999]) # example data

s.where(s.between(*s.quantile([0.25, 0.75])), s.median())

它给你:

0    38.5
1    38.5
2    32.0
3    45.0
4    38.5
5    38.5

解压缩该代码,我们s.quantile([0.25, 0.75])来获取此代码:

0.25    31.25
0.75    48.75

然后我们使用值(31.25和48.75)作为between()的参数,并使用*运算符解压缩它们,因为between()需要两个单独的参数,而不是长度为2的数组那给了我们:

0    False
1    False
2     True
3     True
4    False
5    False

现在我们有二进制掩码,我们使用s.where()选择True位置的原始值,否则返回s.median()

答案 1 :(得分:0)

这就是分位数的定义方式

df = pd.DataFrame(np.array([60,70,80,100,130,150,200,200,250,300,800,1000]))
print df.quantile(.25)
print df.quantile(.50)
print df.quantile(.75)

(数据集的q1为95 btw)

中位数介于150和200之间(175)

第一个分位数是80到100(95)之间的3个季度

第三个分位数是250到300(262.5)

之间的四分之一