在一些数据的预处理过程中,我需要删除一些异常值。由于应用程序的性质,我不能删除数据点本身,所以我想用某个范围内其他数据点的最大值来替换它们。例如,假设下面的玩具示例:
import pandas as pd
from scipy import stats
df = pd.DataFrame({
"Name": ["A", "A", "A", "A", "B", "B", "B", "B"],
"Value": [1, 2, 30, 4, 10, 200, 30, 40],
"Class": ["S", "S", "S", "S", "X", "X", "X", "X"]
})
现在,让我们修改远离一个标准差的点(通常,我们在3倍标准差或99.8%百分位数处进行修改,这里仅以一个标准差为例):
df[["zscore"]] = (
df.groupby(["Name"])
[["Value"]]
.transform(lambda x : stats.zscore(x, ddof=1))
)
这就给了我们这样的结果:
Name Value Class zscore
0 A 1 S -0.593976
1 A 2 S -0.521979
2 A 30 S 1.493940
3 A 4 S -0.377985
4 B 10 X -0.685248
5 B 200 X 1.484705
6 B 30 X -0.456832
7 B 40 X -0.342624
现在,我想用zscore〉= 1.0替换所有值,以获得下表:
Name Value Class zscore
0 A 1 S -0.593976
1 A 2 S -0.521979
2 A 4 S 1.493940
3 A 4 S -0.377985
4 B 10 X -0.685248
5 B 40 X 1.484705
6 B 30 X -0.456832
7 B 40 X -0.342624
请注意,在索引2中,Value
从30更改为4。在索引5中,Value
从200更改为40。
现在,我的 Dataframe 很大(78M+行),我想使用最高效但仍然很短的代码来完成它。我尝试了以下方法,但它不起作用:
indices = df["zscore"] > 1.0
df.loc[indices] = (
df[~indices]
.groupby("Name")
.max("Value")
)
这给了我
Name Value Class zscore
0 A 1.0 S -0.593976
1 A 2.0 S -0.521979
2 NaN NaN NaN NaN
3 A 4.0 S -0.377985
4 B 10.0 X -0.685248
5 NaN NaN NaN NaN
6 B 30.0 X -0.456832
7 B 40.0 X -0.342624
那么,什么是正确的方法呢?保持简短和快速?
当然,我可以做得更详细一点(我不知道这是不是最快的方法):
for name, group in df.groupby("Name"):
indices = group["zscore"] > 1.0
df.loc[group[indices].index, ["Value"]] = group[~indices][["Value"]].max()[0]
它产生了我想要的结果
Name Value Class zscore
0 A 1 S -0.593976
1 A 2 S -0.521979
2 A 4 S 1.493940
3 A 4 S -0.377985
4 B 10 X -0.685248
5 B 40 X 1.484705
6 B 30 X -0.456832
7 B 40 X -0.342624
谢谢你的帮助。
1条答案
按热度按时间wgx48brx1#
假设您有足够的内存来处理数据集,则可以首先掩蔽值列(其中zscore〉1)中的值,然后按名称对掩蔽列进行分组,并使用max进行变换以广播每个组的最大值