使用 .apply、.applymap、.groupby 转换 Pandas DataFrame 中的异常值
Transforming outliers in Pandas DataFrame using .apply, .applymap, .groupby
我正在尝试将 pandas DataFrame 对象转换为包含基于一些简单阈值的点分类的新对象:
- 如果点为
NaN
,则值转换为 0
- 如果点为负或 0
,则值转换为 1
- 如果值不符合基于整列的某些标准,则值转换为
2
- 值为
3
,否则
这是一个非常简单的独立示例:
import pandas as pd
import numpy as np
df=pd.DataFrame({'a':[np.nan,1000000,3,4,5,0,-7,9,10],'b':[2,3,-4,5,6,1000000,7,9,np.nan]})
print(df)
目前创建的转换过程:
#Loop through and find points greater than the mean -- in this simple example, these are the 'outliers'
outliers = pd.DataFrame()
for datapoint in df.columns:
tempser = pd.DataFrame(df[datapoint][np.abs(df[datapoint]) > (df[datapoint].mean())])
outliers = pd.merge(outliers, tempser, right_index=True, left_index=True, how='outer')
outliers[outliers.isnull() == False] = 2
#Classify everything else as "3"
df[df > 0] = 3
#Classify negative and zero points as a "1"
df[df <= 0] = 1
#Update with the outliers
df.update(outliers)
#Everything else is a "0"
df.fillna(value=0, inplace=True)
导致:
我曾尝试使用 .applymap()
and/or .groupby()
in order to speed up the process with no luck. I found some guidance in ,但是,我仍然不确定当您不在 pandas 列中分组时,.groupby()
有何用处。
这是异常值部分的替代品。在我的计算机上,您的示例数据的速度大约快 5 倍。
>>> pd.DataFrame( np.where( np.abs(df) > df.mean(), 2, df ), columns=df.columns )
a b
0 NaN 2
1 2 3
2 3 -4
3 4 5
4 5 6
5 0 2
6 -7 7
7 9 9
8 10 NaN
您也可以使用 apply 来完成,但它会比 np.where
方法慢(但与您当前正在执行的速度大致相同),但要简单得多。这可能是一个很好的例子,说明为什么在关心速度时应尽可能避免 apply
。
>>> df[ df.apply( lambda x: abs(x) > x.mean() ) ] = 2
你也可以这样做,比apply
快但比np.where
慢:
>>> mask = np.abs(df) > df.mean()
>>> df[mask] = 2
当然,这些东西并不总是线性扩展,所以请在您的真实数据上测试它们,看看它们之间的比较。
我正在尝试将 pandas DataFrame 对象转换为包含基于一些简单阈值的点分类的新对象:
- 如果点为
NaN
,则值转换为 - 如果点为负或 0 ,则值转换为
- 如果值不符合基于整列的某些标准,则值转换为
2
- 值为
3
,否则
0
1
这是一个非常简单的独立示例:
import pandas as pd
import numpy as np
df=pd.DataFrame({'a':[np.nan,1000000,3,4,5,0,-7,9,10],'b':[2,3,-4,5,6,1000000,7,9,np.nan]})
print(df)
目前创建的转换过程:
#Loop through and find points greater than the mean -- in this simple example, these are the 'outliers'
outliers = pd.DataFrame()
for datapoint in df.columns:
tempser = pd.DataFrame(df[datapoint][np.abs(df[datapoint]) > (df[datapoint].mean())])
outliers = pd.merge(outliers, tempser, right_index=True, left_index=True, how='outer')
outliers[outliers.isnull() == False] = 2
#Classify everything else as "3"
df[df > 0] = 3
#Classify negative and zero points as a "1"
df[df <= 0] = 1
#Update with the outliers
df.update(outliers)
#Everything else is a "0"
df.fillna(value=0, inplace=True)
导致:
我曾尝试使用 .applymap()
and/or .groupby()
in order to speed up the process with no luck. I found some guidance in .groupby()
有何用处。
这是异常值部分的替代品。在我的计算机上,您的示例数据的速度大约快 5 倍。
>>> pd.DataFrame( np.where( np.abs(df) > df.mean(), 2, df ), columns=df.columns )
a b
0 NaN 2
1 2 3
2 3 -4
3 4 5
4 5 6
5 0 2
6 -7 7
7 9 9
8 10 NaN
您也可以使用 apply 来完成,但它会比 np.where
方法慢(但与您当前正在执行的速度大致相同),但要简单得多。这可能是一个很好的例子,说明为什么在关心速度时应尽可能避免 apply
。
>>> df[ df.apply( lambda x: abs(x) > x.mean() ) ] = 2
你也可以这样做,比apply
快但比np.where
慢:
>>> mask = np.abs(df) > df.mean()
>>> df[mask] = 2
当然,这些东西并不总是线性扩展,所以请在您的真实数据上测试它们,看看它们之间的比较。