如何使用pandas groupby并应用lambda计算布尔条件

如何使用pandas groupby并应用lambda计算布尔条件,lambda,apply,multi-index,pandas-groupby,Lambda,Apply,Multi Index,Pandas Groupby,我一直在自学python如何使用股票数据,但我一直在这个问题上纠缠不休。我试图确定一个移动平均线交叉点。我正在熊猫多索引数据框中处理日常数据。下面是我正在使用的数据结构的一个片段 import pandas as pd import numpy as np data = {'date': pd.Series(['2016-1-4', '2016-1-4', '2016-1-4', '2016-1-5', '2016-1-5', '2016

我一直在自学python如何使用股票数据,但我一直在这个问题上纠缠不休。我试图确定一个移动平均线交叉点。我正在熊猫多索引数据框中处理日常数据。下面是我正在使用的数据结构的一个片段

import pandas as pd
import numpy as np

data = {'date': pd.Series(['2016-1-4', '2016-1-4', '2016-1-4', 
                           '2016-1-5', '2016-1-5', '2016-1-5', 
                           '2016-1-6', '2016-1-6', '2016-1-6']),
        'ticker': pd.Series(['NYMX', 'EVAR', 'PMV', 
                             'NYMX', 'EVAR', 'PMV', 
                             'NYMX', 'EVAR', 'PMV']),
        'twohundredsma': pd.Series([2.3, 3.58, 0.458, 
                                    2.31, 3.56, 0.459, 
                                    2.32, 3.55, 0.46]),
        'fiveema': pd.Series([2.33, 1.31, 0.54, 
                              2.33, 1.28, 0.54, 
                              2.3, 1.25, 0.54])}

df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date'])
df.set_index(['date', 'ticker'], inplace=True)
通过取两条移动平均线之间的差值,并使用
shift
检查前一天符号的变化,可以识别交叉点。我已经测试过这种方法(没有groupby),它工作得很好,在交叉发生时提供
True

然而,我遇到的问题是使用
groupby
函数将此函数应用于每个股票行情。我最初的方法是使用
apply
lambda
函数。下面的代码添加了2个新列,但“five200bull”列中填充了“nan”值,没有抛出错误

def five_cross(df):
    df['fiveminus200'] = df['fiveema'] - df['twohundredsma']    

    df['five200bull'] = df.groupby(level='ticker').apply(lambda x: 
      np.sign(x['fiveminus200'])!=np.sign(x['fiveminus200'].shift(1)))
所以我尝试了一种不同的方法,将每个ticker作为一个数据帧传递给一个单独的函数。这种方法在处理大型数据帧时要慢得多,但也不起作用

def add_five_bull(df):
    df['five200bull'] = np.sign(df['fiveminus200']) != np.sign(df['fiveminus200'].shift(1))

def five_cross(df):
    df['fiveminus200'] = df['fiveema'] - df['twohundredsma']    

    # group by ticker
    grouped = df.groupby(level='ticker')

    # pass each ticker in a df to function
    for tick, group in grouped:
        add_five_bull(group)
使用这种方法,“five200bull”列永远不会附加到df中,我收到了声名狼藉的
设置和CopyWarning
。我尝试将
df.loc[:,'fiveminus200']
添加到
add\u five\u bull
函数中,但除了使用大数据集花费更长的时间外,似乎没有任何结果


很明显,我的逻辑有一些缺陷,如果能帮我解决这个问题,我将不胜感激

我相信您需要参数
group_keys=False
来删除输出中附加的新级别-然后验证数据。还返回每组的第一个值
NaN
,因此
np。签名
raise warning:

RuntimeWarning:在符号中遇到无效值 np.符号(x['fiveminus200'])=np.符号(x['fiveminus200'].移位(1)))

解决方案是将
NaN
替换为某个值,例如
False
True



谢谢,我需要的正是
group\u keys=False
!我检查了文档,它清楚地告诉我在调用
apply
时使用它,但我没有看到。
fillna
似乎没有任何作用。第一行返回
True
,无论我是否将其放入。
def five_cross(df):
    df['fiveminus200'] = df['fiveema'] - df['twohundredsma']    

    df['five200bull'] = df.groupby(level='ticker', group_keys=False).apply(lambda x: 
      np.sign(x['fiveminus200'])!=np.sign(x['fiveminus200'].shift(1).fillna(False)))
    return df  

print (five_cross(df))
                   fiveema  twohundredsma  fiveminus200  five200bull
date       ticker                                                   
2016-01-04 NYMX       2.33          2.300         0.030         True
           EVAR       1.31          3.580        -2.270         True
           PMV        0.54          0.458         0.082         True
2016-01-05 NYMX       2.33          2.310         0.020        False
           EVAR       1.28          3.560        -2.280        False
           PMV        0.54          0.459         0.081        False
2016-01-06 NYMX       2.30          2.320        -0.020         True
           EVAR       1.25          3.550        -2.300        False
           PMV        0.54          0.460         0.080        False
def five_cross(df):
    df['fiveminus200'] = df['fiveema'] - df['twohundredsma']    

    df1 = df.groupby(level='ticker').apply(lambda x: 
      np.sign(x['fiveminus200'])!=np.sign(x['fiveminus200'].shift(1).fillna(False)))
    return df1 

print (five_cross(df))
ticker  date        ticker
EVAR    2016-01-04  EVAR       True
        2016-01-05  EVAR      False
        2016-01-06  EVAR      False
NYMX    2016-01-04  NYMX       True
        2016-01-05  NYMX      False
        2016-01-06  NYMX       True
PMV     2016-01-04  PMV        True
        2016-01-05  PMV       False
        2016-01-06  PMV       False
Name: fiveminus200, dtype: bool