Python 熊猫“滚动应用”和TypeError的乐趣

Python 熊猫“滚动应用”和TypeError的乐趣,python,pandas,Python,Pandas,我真的很难使用Pandasrolling\u apply函数。我正在尝试对一些时间序列数据应用一个过滤器,如下面所示,并为异常值创建一个新的序列。当值是异常值时,我希望该值返回True ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)) window, alpha, gamma = 60, .05, .03 def trim_moments(arr, alpha):

我真的很难使用Pandas
rolling\u apply函数。我正在尝试对一些时间序列数据应用一个过滤器,如下面所示,并为异常值创建一个新的序列。当值是异常值时,我希望该值返回
True

ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))

window, alpha, gamma = 60, .05, .03

def trim_moments(arr, alpha):
    np.sort(arr)
    n = len(arr)
    k = int(round(n*float(alpha))/2)
    return np.mean(arr[k+1:n-k]), np.std(arr[k+1:n-k])

# First function that tests whether criteria is met.
def bg_test(arr,alpha,gamma):
    local_mean, local_std = trim_moments(arr, alpha)
    return np.abs(arr - local_mean) < 3 * local_std + gamma
返回错误:

TypeError: only length-1 arrays can be converted to Python scalars
我的故障排除表明问题在于布尔返回语句。当我简化函数并使用
np.mean/std
而不是我自己的函数时,我不断得到类似的错误。以前出现的
TypeError
问题似乎是由于在Numpy数组上执行非矢量化操作造成的,但这似乎不是问题所在


我在这里做错了什么?

这不是一条有用的消息,但我相信错误正在发生,因为
rolling\u apply
当前需要一个类似类型的返回数组(甚至可能必须是float)。但是,如果您将三个操作(mean、std、outlier逻辑)分解为多个步骤,它应该可以正常工作

ts.name = 'value'

df = pd.DataFrame(ts)

def trimmed_apply(arr, alpha, f):
    np.sort(arr)
    n = len(arr)
    k = int(round(n*float(alpha))/2)
    return f(arr[k+1:n-k])

df['trimmed_mean'] = pd.rolling_apply(df['value'], window, trimmed_apply, args=(alpha, np.mean))
df['trimmed_std'] = pd.rolling_apply(df['value'], window, trimmed_apply, args=(alpha, np.std))

df['outlier'] = np.abs(arr - df['trimmed_mean']) < 3 *  df['trimmed_std'] + gamma
ts.name='value'
df=pd.数据帧(ts)
def微调_应用(arr、alpha、f):
np.排序(arr)
n=长度(arr)
k=int(圆形(n*float(alpha))/2)
返回f(arr[k+1:n-k])
df['trimmed_mean']=pd.rolling_apply(df['value'],窗口,trimmed_apply,args=(alpha,np.mean))
df['trimmed_std']=pd.rolling_apply(df['value'],窗口,trimmed_apply,args=(alpha,np.std))
df['outlier']=np.abs(arr-df['trimmed_mean'])<3*df['trimmed_std']+gamma

我不仅要感谢您提供的有效解决方案,还要感谢您如何组织
trim\u apply
功能。非常方便!令人惊讶的是,这只会将我以前的解决方案(通过
pd.iterrows()
完成)的速度提高3-5倍。我原本希望避免迭代会带来更好的收益。
ts.name = 'value'

df = pd.DataFrame(ts)

def trimmed_apply(arr, alpha, f):
    np.sort(arr)
    n = len(arr)
    k = int(round(n*float(alpha))/2)
    return f(arr[k+1:n-k])

df['trimmed_mean'] = pd.rolling_apply(df['value'], window, trimmed_apply, args=(alpha, np.mean))
df['trimmed_std'] = pd.rolling_apply(df['value'], window, trimmed_apply, args=(alpha, np.std))

df['outlier'] = np.abs(arr - df['trimmed_mean']) < 3 *  df['trimmed_std'] + gamma