我正在尝试将pandas数据帧对象转换为包含基于一些简单阈值的点分类的新对象:
如果点0
如果点为负或0,则值转换为NaN
如果值超出基于整列的特定条件,则转换为1
否则值2
下面是一个非常简单的自包含示例:

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)

导致:
我试着使用3和/或.applymap()来加速这个过程,但没有成功。我在this answer中找到了一些指导,但是,当您不在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

你也可以用Apple来做,但是它会比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

当然,这些东西并不总是线性的,所以在你的真实数据上测试它们,看看它们是如何比较的。

10-08 08:09
查看更多