1
votes

I'm trying to iterate Numpy values, but I seem to be getting an error.

for ax in [ax1, ax2, ax3]:
   ax.axvline(enter_pos, c ='g')
   ax.axvline(exit_pos, c = 'r')

But I get this error:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I know there are other answers on Stackover flow with this problem, but I have no idea what to do. The answers don't highlight how to change the code to accommodate a for loop, which is what has seem to have tripped me up.

I've tried:

ax in [ax1], ax in [ax2], ax in [ax3]

ax[ax1 & ax2 & ax3]

But nothing has worked yet.

Ideas?

* Edit *

Here is more of the code:

    ax1 = plt.subplot(311)
    data[[ticker[0], ticker[1]]].plot(ax = ax1)
    plt.ylabel('Price')
    plt.setp(ax1.get_xticklabels(), visible=False)

    ax2 = plt.subplot(312, sharex=ax1)
    results.spread.plot(ax=ax2, color='k')
    ax2.axhline(2, color='k')
    ax2.axhline(5, color='k')
    plt.ylabel('Spread')
    plt.setp(ax2.get_xticklabels(), visible=False)

    ax3 = plt.subplot(313, sharex=ax1)
    results.portfolio_value.plot(ax=ax3, color='k')
    plt.ylabel('Portfolio Value')

    # Plot spread enter and exit markers
    enter_pos = results.index[results.buy_spread]
    exit_pos = results.index[results.sell_spread]

    for ax in [ax1, ax2, ax3]:
        ax.axvline(enter_pos, c ='g')
        ax.axvline(exit_pos, c = 'r')

    plt.gcf().set_size_inches(16, 12)

* EDIT 2 *

I want to say the comment about the second loop is correct, but I still get the same error with this code:

for ax in [ax1, ax2, ax3]:
  for pos in enter_pos:
    ax.axvline(enter_pos, c ='g')
    ax.axvline(exit_pos, c = 'r')
1
Can you post the full traceback? As is, it's hard to see exactly why the error is being thrown. It looks like you're trying to iterate over matplotlib axes which doesn't have much to do with the exception you're seeing. The exception probably has to do with enter_pos and exit_pos... - mgilson

1 Answers

2
votes

axvline only support one number, you need a second loop:

for ax in [ax1, ax2, ax3]:
    for pos in enter_pos:
        ax.axvline(pos, c ='g')
    for pos in exit_pos:
        ax.axvline(pos, c ='r')

but if the size of enter_pos is large it maybe slow. You can use LineCollection istead, here is an example:

import pylab as pl
import numpy as np
from matplotlib import collections
from matplotlib import transforms

def axvlines(ax, x, **kw):
    from matplotlib import collections
    from matplotlib import transforms

    x = np.asanyarray(x)
    y0 = np.zeros_like(x)
    y1 = np.ones_like(x)        
    data = np.c_[x, y0, x, y1].reshape(-1, 2, 2)
    trans = transforms.blended_transform_factory(ax.transData, ax.transAxes)
    lines = collections.LineCollection(data, transform=trans, **kw)
    ax.add_collection(lines)

You can use it as:

axvlines(enter_pos, colors="g")
axvlines(exit_pos, colors="r")

By using axvlines(), you can even create a colormap for the lines:

X = np.logspace(-1, 0, 50)
fig, ax = pl.subplots()
axvlines(ax, X, cmap="jet", array=np.linspace(0, 1, 50))

Here is the output:

enter image description here