提问人:Anakin Skywalker 提问时间:8/14/2023 最后编辑:Anakin Skywalker 更新时间:8/15/2023 访问量:70
在 Python 中为具有不同实际值的多列删除异常值并计算修剪后的平均值
Removing outliers and calculating a trimmed mean in Python for multiple columns with different number of actual values
问:
我有一个数据集。假设有 10010 行和 100 列,列值可能包括 NaN,并且每列 NaN 可以不同。
我想要
- 从该数据集中选取 n 个列(假设 20 列,不带顺序,例如 Column1、Column2 等)。
- 修剪异常值(每个选定列的最高值的 2.5% 和最低值的 2.5%),不包括 NaN 值(因此,如果 10010 个值中有 10 个值是 Column1 中的 NaN,我需要从顶部修剪掉实际最高的 250 个值,从 10000 个值的底部修剪掉 250 个实际最低值)
- 但是,如果 Column2 最初有 110 NaN,我想从每侧修剪 2.5% 的实际值数(在本例中为 9900,而不是像 Column1 列中的 10000)
- 计算每个选定列的修剪平均值
- 修剪后有一个新数据集,其中所有修剪的异常值都转换为 NaN
答:
2赞
user19077881
8/14/2023
#1
下面的这个简化示例显示了一种可能有用的方法,并使用 pd.quantile。代码可以根据您的要求进行开发(显然包括分位数参数)。
import pandas as pd
df = pd.DataFrame({'col1': [ 1, 2, 3, 4, None, 6, 7, 8, 54],
'col2': [3, 5, 13, 14, 2, 16, 17, 18, 19] })
cols = ['col1', 'col2']
for col in cols:
lo = df[col].quantile(0.1)
hi = df[col].quantile(0.9)
df[col] = df[col].where((df[col]> lo) & (df[col] < hi), None)
print(f'mean for {col} is: ', df[col].mean().round(2))
print(df)
给:
mean for col1 is: 5.0
mean for col2 is: 12.29
col1 col2
0 NaN 3.0
1 2.0 5.0
2 3.0 13.0
3 4.0 14.0
4 NaN NaN
5 6.0 16.0
6 7.0 17.0
7 8.0 18.0
8 NaN NaN
上面的代码使用值阈值将异常值更改为 NaN;这将是通常的方法。 如果要求是在任一极端更改多个值,那么这可能是 通过保存和操作索引、按值排序、更改异常值来完成 比例,然后使用索引恢复原始顺序。下面的代码假设 最初使用了默认的数字索引;如果不是,则用户 索引需要保存,然后最终重新恢复。
cut_val = 0.2 # proportion of non_NaN values to remove from each extreme
num_rows = len(df)
cols = ['col1', 'col2']
for col in cols:
num_not_nan = num_rows - df[col].isna().sum()
cut = int(num_not_nan*cut_val)
dfx = df[col].sort_values()
idx = dfx.index.to_list() #save sorted index
dfx.index = range(num_rows) #use numerical re-index so .loc can be used
dfx.loc[0:cut-1] = None
dfx.loc[num_not_nan-cut:num_not_nan] = None
dfx.index=idx #impose original index
df[col] = dfx.sort_index()
print(f'mean for {col} is: ', df[col].mean().round(2))
print(df)
评论
0赞
Anakin Skywalker
8/15/2023
一个问题。你的代码很棒,它可以修剪低于和高于阈值的所有内容。如何额外更新此代码,而不是根据特定值删除异常值,而是删除值的数量。例如,如果我有 10000(其中 9 个留空),那么 10000 的 2.5% = 250 个值,我将删除前 250 个值和后 250 个值,然后计算修剪后的平均值。你看到区别了吗?例如,如果值 2 在阈值范围内,则您的代码会将所有值 = 2 转换为 NaN,但我想删除特定数量的值,而不是所有值 <=2(例如)
1赞
user19077881
8/15/2023
请参阅我认为符合此值数量要求的编辑答案,
上一个:在 R 中剪裁数据
评论