【问题标题】:Getting warning "TimeSeries broadcasting along DataFrame index by default is deprecated"收到警告“默认情况下沿 DataFrame 索引广播的 TimeSeries 已弃用”
【发布时间】:2014-04-17 00:05:28
【问题描述】:

我正在使用 Python 2.7 并不断收到以下错误。如果您需要完整的代码,请告诉我,但它有点长。感谢您的帮助。

Warning (from warnings module):
  File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 3619
FutureWarning)
FutureWarning: TimeSeries broadcasting along DataFrame index by default is deprecated.     
Please use DataFrame.<op> to explicitly broadcast arithmetic operations along the index

这里是类 Portfolio

class Portfolio(object):
"""An abstract base class representing a portfolio of 
positions (including both instruments and cash), determined
on the basis of a set of signals provided by a Strategy."""

__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def generate_positions(self):
    raise NotImplementedError("Should implement generate_positions()!")

@abc.abstractmethod
def backtest_portfolio(self):
    raise NotImplementedError("Should implement backtest_portfolio()!")

这是导致 name == "ma​​in"

中问题的代码
import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from pandas.io.data import DataReader
from backtest import Strategy, Portfolio

class MovingAverageCrossStrategy(Strategy):

def __init__(self, symbol, bars, short_window=8, long_window=50):
    self.symbol = symbol
    self.bars = bars

    self.short_window = short_window
    self.long_window = long_window

def generate_signals(self):
    signals = pd.DataFrame(index=self.bars.index)
    signals['signal'] = 0.0

    # Create the set of short and long simple moving averages over the 
    # respective periods
    signals['short_mavg'] = pd.rolling_mean(bars['Close'], self.short_window, min_periods=1)
    signals['long_mavg'] = pd.rolling_mean(bars['Close'], self.long_window, min_periods=1)

    # Create a 'signal' (invested or not invested) when the short moving average crosses the long
    # moving average, but only for the period greater than the shortest moving average window
    signals['signal'][self.short_window:] = np.where(signals['short_mavg'][self.short_window:]
                                                     > signals['long_mavg'][self.short_window:], 1.0, 0.0)   

    # Take the difference of the signals in order to generate actual trading orders
    signals['positions'] = signals['signal'].diff()   

    return signals

class MarketOnClosePortfolio(Portfolio):

def __init__(self, symbol, bars, signals, initial_capital=100000.0):
    self.symbol = symbol        
    self.bars = bars
    self.signals = signals
    self.initial_capital = float(initial_capital)
    self.positions = self.generate_positions()

def generate_positions(self):
    positions = pd.DataFrame(index=signals.index).fillna(0.0)
    positions[self.symbol] = 100*signals['signal']   # This strategy buys 100 shares
    return positions

def backtest_portfolio(self):
    portfolio = self.positions*self.bars['Close']
    pos_diff = self.positions.diff()

    portfolio['holdings'] = (self.positions*self.bars['Close']).sum(axis=1)
    portfolio['cash'] = self.initial_capital - (pos_diff*self.bars['Close']).sum(axis=1).cumsum()

    portfolio['total'] = portfolio['cash'] + portfolio['holdings']
    portfolio['returns'] = portfolio['total'].pct_change()
    return portfolio

if __name__ == "__main__":
# Obtain daily bars of stock from Yahoo Finance for the period
# 1st Jan 1990 to 1st Jan 2014 - This is an example from ZipLine
symbol = 'AAPL'
bars = DataReader(symbol, "yahoo", datetime.datetime(1990,1,1), datetime.datetime(2014,1,1))

# Create a Moving Average Cross Strategy instance with a short moving
# average window of 8 days and a long window of 50 days
mac = MovingAverageCrossStrategy(symbol, bars, short_window=8, long_window=50)
signals = mac.generate_signals()

# Create a portfolio of stock, with $100,000 initial capital
portfolio = MarketOnClosePortfolio(symbol, bars, signals, initial_capital=100000.0)
returns = portfolio.backtest_portfolio()

【问题讨论】:

  • 1) 请将代码缩减为能够重现警告且不会太长的内容 2) 您的问题是什么?
  • 嗨保罗,我想我的问题是,为什么会发生这个错误以及如何理解这个错误。
  • 我很乐意提供帮助,但我没有时间去体验那么好的东西。请将其归结为生成您的 pandas 对象并执行生成警告的操作的几行代码。这样做可以让其他人更容易提供帮助,并让其他人在遇到这种情况时更容易解决自己的问题。
  • 例如,你看到的错误与绘图无关,所以把那些东西删掉。
  • 请参阅文档中的此部分:pandas.pydata.org/pandas-docs/stable/…,了解您收到警告的原因。 Previsouly 当例如添加一个带有 datetimeindex 的数据框和一个带有 datetimeindex 的系列时,它将在索引上对齐(而不是与其他数据框一样的列)。这没有被弃用,您应该使用专用方法。

标签: python error-handling module pandas


【解决方案1】:

由于无法运行您的代码,很难指出确切的原因,但以generate_positions 中的这一行为例:

portfolio = self.positions*self.bars['Close']

假设self.positions 是一个DataFrame,self.bars['Close'] 是一个Series(在这种情况下是DataFrame 的一列,它作为一个Series 返回)。我试着用一个玩具例子来解释这个问题:

首先生成一个数据框和一个系列(带有日期时间索引):

In [3]: idx = pd.date_range('2012-01-01', periods=3)
In [5]: df = pd.DataFrame({'A':[1,2,3], 'B':[10,20,30]}, index=idx)
In [6]: df
Out[6]: 
            A   B
2012-01-01  1  10
2012-01-02  2  20
2012-01-03  3  30

In [7]: s = pd.Series([1,2,3], index=idx)
In [8]: s
Out[8]: 
2012-01-01    1
2012-01-02    2
2012-01-03    3
Freq: D, dtype: int64

现在,如果我们将两者相乘,我们将收到您注意到的警告:

In [10]: df * s
/home/joris/scipy/pandas-np16/pandas/core/frame.py:2920: FutureWarning: TimeSeries 
broadcasting along DataFrame index by default is deprecated. Please use DataFrame.<op> 
to explicitly broadcast arithmetic operations along the index
  FutureWarning)
Out[10]: 
            A   B
2012-01-01  1  10
2012-01-02  4  40
2012-01-03  9  90

这是因为我在 cmets 中提到的内容,并在此处进行了解释:http://pandas.pydata.org/pandas-docs/stable/dsintro.html?highlight=broadcasting#data-alignment-and-arithmetic。通常,如果数据帧和系列相乘,系列会在列上广播,而对于时间序列,这是在行上完成的。但这已被弃用。
因此,您应该使用等效的运算符作为警告建议。如果是乘法:

In [13]: df.mul(s, axis=0)
Out[13]: 
            A   B
2012-01-01  1  10
2012-01-02  4  40
2012-01-03  9  90

因此,对于每个运算符(+、*;、/ 等),都有一个等效的方法。方法列表见这里:http://pandas.pydata.org/pandas-docs/stable/api.html#id4 [url updated]


为了说明“在列上广播”的含义,再举一个例子:

In [14]: s2 = pd.Series([10, 100],  index=['A', 'B'])

In [15]: s2
Out[15]: 
A     10
B    100
dtype: int64

In [16]: df * s2
Out[16]: 
             A     B
2012-01-01  10  1000
2012-01-02  20  2000
2012-01-03  30  3000

如您所见,该系列的每个元素都与一列匹配,然后将整列与该值相乘。而在时间序列的情况下,序列的每个元素都与一行匹配。

【讨论】:

  • joris - 很好的解释。由于这对我来说仍然是新的,我明白你想说什么。它基本上是数据帧与系列的乘法发生方式的区别......现在,您是否还建议通过将运算符函数更改为类似 '''DataFrame.mul(other[, axis, level, fill_value]) ''' 那么这可能会解决问题吗?
  • 是的,所以如果您将所有出现的 +、-、*、/、 等在您有数据框和系列的地方更改为相应的方法,这将解决问题(警告,目前它会给出相同的结果。但将来会改变,只有方法仍然有效)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-26
相关资源
最近更新 更多