1

这是设置:

arrays = [["2010-01-01","2010-01-01","2010-01-02","2010-01-02","2010-01-03","2010-01-03"],
                 ["MSFT", "AAPL", "MSFT", "AAPL","MSFT", "AAPL"]]

tuples = list(zip(*arrays))

index = pd.MultiIndex.from_tuples(tuples, names=["date", "symbol"])

df = pd.DataFrame(data=np.random.randn(6, 4), index=index, columns=["high", "low", "open", "close"])

def fn_sum(close, high, low):
    return close+high+low

def fn_plus(close):
        return close+1

DF 看起来像这样:

date       symbol   high        low        open        close

2010-01-01  MSFT  1.144042   0.889603   -0.193715   1.005927
            AAPL  0.433530  -0.291510    1.420505   0.326206
2010-01-02  MSFT -1.509419  -0.273476   -0.620735  -0.205946
            AAPL  0.454401  -0.085008    0.686485   1.309894
2010-01-03  MSFT  1.487588  -0.777500   -0.218993  -1.242664
            AAPL -0.456024  -0.819463   -2.224953   1.263124

我想对所有具有 groupby()、apply() 方式的符号使用技术分析函数,如下所示:

df["1"] = df.groupby(level="symbol").apply(lambda x: fn_sum(x["close"], x["high"], x["low"]))

这会导致广播错误:

ValueError: operands could not be broadcast together with shapes (6,2) (3,) (6,2)

但是,在单个列上执行相同的操作可以:

df["2"] = df.groupby(level="symbol").close.apply(lambda x: fn_plus(x))

问题:

  • 那么,当在多个列上使用 apply 并将它们组合回 DataFrame 而不会出现广播问题时,我该如何让它工作呢?

  • 另外,我非常感谢与上面的 MultiIndex DF 一起使用的更好的实现。

有关更多上下文:我想使用 TA-lib 包中的技术分析功能。见:https ://mrjbq7.github.io/ta-lib/func_groups/volatility_indicators.html

函数如下所示(例如):

ATR(高,低,收盘[,时间段=?])

平均真实范围(波动率指标)

输入:价格:['high','low','close'] 参数:时间段:14 输出:real

在人为的示例中,我得到了与上面相同的广播错误。

4

1 回答 1

2

如果需要多列传递给函数使用DataFrame.joinDataFrame.assign

s = (df.groupby(level="symbol", group_keys=False)
       .apply(lambda x: fn_sum(x["close"], x["high"], x["low"])))
df = df.join(s.rename('new'))
#alternative
#df = df.assign(new=s)
print (df)
                       high       low      open     close       new
date       symbol                                                  
2010-01-01 MSFT   -1.085631  0.997345  0.282978 -1.506295 -1.594580
           AAPL   -0.578600  1.651437 -2.426679 -0.428913  0.643924
2010-01-02 MSFT    1.265936 -0.866740 -0.678886 -0.094709  0.304487
           AAPL    1.491390 -0.638902 -0.443982 -0.434351  0.418136
2010-01-03 MSFT    2.205930  2.186786  1.004054  0.386186  4.778903
           AAPL    0.737369  1.490732 -0.935834  1.175829  3.403930

如果只有一列使用GroupBy.transform并在之后指定列groupby

df['new1'] = df.groupby(level="symbol")['close'].transform(fn_plus)
print (df)
                       high       low      open     close      new1
date       symbol                                                  
2010-01-01 MSFT   -1.085631  0.997345  0.282978 -1.506295 -0.506295
           AAPL   -0.578600  1.651437 -2.426679 -0.428913  0.571087
2010-01-02 MSFT    1.265936 -0.866740 -0.678886 -0.094709  0.905291
           AAPL    1.491390 -0.638902 -0.443982 -0.434351  0.565649
2010-01-03 MSFT    2.205930  2.186786  1.004054  0.386186  1.386186
           AAPL    0.737369  1.490732 -0.935834  1.175829  2.175829
于 2019-04-16T07:46:34.113 回答