我有一个很少列的熊猫数据帧。
现在我知道某些行是基于某个列值的异常值。
例如
列“Vol”的所有值都在12xx左右,其中一个值是4000(离群值)。
现在我想排除那些Vol列像这样的行。
所以,本质上,我需要在数据帧上放一个过滤器,这样我们就可以选择所有的行,其中某一列的值距离平均值在3个标准差之内。
实现这一点的优雅方式是什么?
我有一个很少列的熊猫数据帧。
现在我知道某些行是基于某个列值的异常值。
例如
列“Vol”的所有值都在12xx左右,其中一个值是4000(离群值)。
现在我想排除那些Vol列像这样的行。
所以,本质上,我需要在数据帧上放一个过滤器,这样我们就可以选择所有的行,其中某一列的值距离平均值在3个标准差之内。
实现这一点的优雅方式是什么?
当前回答
对于数据框架中的每个系列,您可以使用between和分位数来删除异常值。
x = pd.Series(np.random.normal(size=200)) # with outliers
x = x[x.between(x.quantile(.25), x.quantile(.75))] # without outliers
其他回答
你可以使用布尔掩码:
import pandas as pd
def remove_outliers(df, q=0.05):
upper = df.quantile(1-q)
lower = df.quantile(q)
mask = (df < upper) & (df > lower)
return mask
t = pd.DataFrame({'train': [1,1,2,3,4,5,6,7,8,9,9],
'y': [1,0,0,1,1,0,0,1,1,1,0]})
mask = remove_outliers(t['train'], 0.1)
print(t[mask])
输出:
train y
2 2 0
3 3 1
4 4 1
5 5 0
6 6 0
7 7 1
8 8 1
由于我正处于我的数据科学之旅的早期阶段,我使用下面的代码来处理异常值。
#Outlier Treatment
def outlier_detect(df):
for i in df.describe().columns:
Q1=df.describe().at['25%',i]
Q3=df.describe().at['75%',i]
IQR=Q3 - Q1
LTV=Q1 - 1.5 * IQR
UTV=Q3 + 1.5 * IQR
x=np.array(df[i])
p=[]
for j in x:
if j < LTV or j>UTV:
p.append(df[i].median())
else:
p.append(j)
df[i]=p
return df
另一种选择是转换数据,以减轻异常值的影响。你可以通过winsorize你的数据来做到这一点。
import pandas as pd
from scipy.stats import mstats
%matplotlib inline
test_data = pd.Series(range(30))
test_data.plot()
# Truncate values to the 5th and 95th percentiles
transformed_test_data = pd.Series(mstats.winsorize(test_data, limits=[0.05, 0.05]))
transformed_test_data.plot()
对于你的每一个数据帧列,你可以得到分位数:
q = df["col"].quantile(0.99)
然后用:
df[df["col"] < q]
如果需要移除上下异常值,将condition与and语句结合:
q_low = df["col"].quantile(0.01)
q_hi = df["col"].quantile(0.99)
df_filtered = df[(df["col"] < q_hi) & (df["col"] > q_low)]
scipy。Stats有方法trim1()和trimboth(),根据排名和被删除值的引入百分比,在单行中删除异常值。