too many values to unpack with a bar chart

I usually do this for line graphs with markers:

    line, = self.subplot.plot_date(dates,data)

along with some keywords to tweak the plot. I then add line to a
dictionary to keep track of it:

    self.line_to_data_dict[line] = self.activity

But today I tried this with a bar chart, just changing plot_date to
bar and renaming the "line," to "bars,":

    fake_data = [2,2,5]
    bars, = self.subplot.bar(fake_data, fake_data )

This gave me the error: ValueError: too many values to unpack.

OK, so if I removed the comma from "bars," so it is just "bars", it
goes through but then I cannot add it to my dictionary--I get:

TypeError: list objects are unhashable

Help in understanding this and a better approach would be helpful. Thanks,
Che

Just a thought, are you trying out the new legend code? Could you do
a print of the type for bars?

Ben Root

···

On Wednesday, January 26, 2011, C M <cmpython@...287...> wrote:

I usually do this for line graphs with markers:

line, = self\.subplot\.plot\_date\(dates,data\)

along with some keywords to tweak the plot. I then add line to a
dictionary to keep track of it:

self\.line\_to\_data\_dict\[line\] = self\.activity

But today I tried this with a bar chart, just changing plot_date to
bar and renaming the "line," to "bars,":

fake\_data = \[2,2,5\]
bars, = self\.subplot\.bar\(fake\_data, fake\_data \)

This gave me the error: ValueError: too many values to unpack.

OK, so if I removed the comma from "bars," so it is just "bars", it
goes through but then I cannot add it to my dictionary--I get:

TypeError: list objects are unhashable

Help in understanding this and a better approach would be helpful. Thanks,
Che

Just a thought, are you trying out the new legend code?

I don't know if I am or not. But these problems are prior to any code
regarding the legend.

Could you do a print of the type for bars?

When I write it as just bars without the comma it is:

bars type = <type 'list'>

If I write it with the comma ( bars,) then it won't even run because
of the ValueError.

I know the 2nd problem is that a dictionary cannot have a mutable
object like a list as a key. But previously, as I said, I was able to
call line, (with the comma) and it would work. In fact, line, with a
comma gives this type:

line type = <class 'matplotlib.lines.Line2D'>

Thanks,
Che

If you just want a hashable object, can you just cast it to a tuple?

  bars = self.subplot.bar(fake_data, fake_data )
  bars_tuple = tuple(bars)

bars_tuple can be used as a dictionary key.

Regards,

-JJ

···

On Thu, Jan 27, 2011 at 10:07 AM, C M <cmpython@...287...> wrote:

I know the 2nd problem is that a dictionary cannot have a mutable
object like a list as a key. But previously, as I said, I was able to
call line, (with the comma) and it would work. In fact, line, with a
comma gives this type:

Yes, that can work, thanks, but I am still stuck without a bar chart
for other reasons (see point #3 below), and I am still confused. I
have some questions that if answered can hopefully help me get
clearer:

1) What does the comma do exactly? If I put this: "line," I create a
matplotlib line object, whereas if I put just "line" I create a list.
  Does this mean that plot() in mpl returns a tuple that contains one
element, which is a mpl line object? (If so, why doesn't it just
return the line object itself?)

2) Why does line, followed by plot() return a mpl line object but
bars, followed by bar() not return some kind of matplotlib object
(like a line)? Why does it instead give the "ValueError: Too many
values to unpack" error?

3) I am getting just hammered with the following error *a lot* in date
plotting lately:

ValueError: ordinal must be >= 1

And I can't figure out what sorts of mistakes or situations are
triggering it. More of the traceback above that error is at the end
of this message. Does someone know when this error will be thrown
when using dates so I can at least know what to check for in my data?

Thanks,
Che

------ more of Traceback:

    for ylabel_i in self.subplot.get_yticklabels():
  File "C:\Python25\lib\site-packages\matplotlib\axes.py", line 2646,
in get_yticklabels
    self.yaxis.get_ticklabels(minor=minor))
  File "C:\Python25\lib\site-packages\matplotlib\axis.py", line 1087,
in get_ticklabels
    return self.get_majorticklabels()
  File "C:\Python25\lib\site-packages\matplotlib\axis.py", line 1071,
in get_majorticklabels
    ticks = self.get_major_ticks()
  File "C:\Python25\lib\site-packages\matplotlib\axis.py", line 1169,
in get_major_ticks
    numticks = len(self.get_major_locator()())
  File "C:\Python25\lib\site-packages\matplotlib\dates.py", line 743,
in __call__
    self.refresh()
  File "C:\Python25\lib\site-packages\matplotlib\dates.py", line 752, in refresh
    dmin, dmax = self.viewlim_to_dt()
  File "C:\Python25\lib\site-packages\matplotlib\dates.py", line 524,
in viewlim_to_dt
    return num2date(vmin, self.tz), num2date(vmax, self.tz)
  File "C:\Python25\lib\site-packages\matplotlib\dates.py", line 289,
in num2date
    if not cbook.iterable(x): return _from_ordinalf(x, tz)
  File "C:\Python25\lib\site-packages\matplotlib\dates.py", line 203,
in _from_ordinalf
    dt = datetime.datetime.fromordinal(ix)
ValueError: ordinal must be >= 1

···

On Wed, Jan 26, 2011 at 9:16 PM, Jae-Joon Lee <lee.j.joon@...287...> wrote:

On Thu, Jan 27, 2011 at 10:07 AM, C M <cmpython@...287...> wrote:

I know the 2nd problem is that a dictionary cannot have a mutable
object like a list as a key. But previously, as I said, I was able to
call line, (with the comma) and it would work. In fact, line, with a
comma gives this type:

If you just want a hashable object, can you just cast it to a tuple?

bars = self.subplot.bar(fake_data, fake_data )
bars_tuple = tuple(bars)

bars_tuple can be used as a dictionary key.

3) I am getting just hammered with the following error *a lot* in date
plotting lately:

ValueError: ordinal must be >= 1

OK, I made up a small runnable sample to show this with bar(). (Using
code that someone else wrote[1]). This code runs when using
plot_date(), but if you comment that out and comment in the ax.bar()
line, it will give this ValueError.

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import datetime as dt

# Make a series of events 1 day apart
x = mpl.dates.drange(dt.datetime(2009,10,1),
                     dt.datetime(2010,1,15),
                     dt.timedelta(days=1))
# Vary the datetimes so that they occur at random times
# Remember, 1.0 is equivalent to 1 day in this case...
x += np.random.random(x.size)

# We can extract the time by using a modulo 1, and adding an arbitrary base date
times = x % 1 + int(x[0]) # (The int is so the y-axis starts at midnight...)

# I'm just plotting points here, but you could just as easily use a bar.
fig = plt.figure()
ax = fig.add_subplot(111)

#comment out:
ax.plot_date(x, times, 'ro')

#comment in
#ax.bar(x, times)

ax.yaxis_date()
fig.autofmt_xdate()

plt.show()

[1]python - plot time of day vs date in matplotlib - Stack Overflow

C M, on 2011-01-27 02:03, wrote:

> 3) I am getting just hammered with the following error *a lot* in date
> plotting lately:
>
> ValueError: ordinal must be >= 1

OK, I made up a small runnable sample to show this with bar(). (Using
code that someone else wrote[1]). This code runs when using
plot_date(), but if you comment that out and comment in the ax.bar()
line, it will give this ValueError.

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import datetime as dt

# Make a series of events 1 day apart
x = mpl.dates.drange(dt.datetime(2009,10,1),
                     dt.datetime(2010,1,15),
                     dt.timedelta(days=1))
# Vary the datetimes so that they occur at random times
# Remember, 1.0 is equivalent to 1 day in this case...
x += np.random.random(x.size)

# We can extract the time by using a modulo 1, and adding an arbitrary base date
times = x % 1 + int(x[0]) # (The int is so the y-axis starts at midnight...)

# I'm just plotting points here, but you could just as easily use a bar.
fig = plt.figure()
ax = fig.add_subplot(111)

#comment out:
ax.plot_date(x, times, 'ro')

Hi C. M.,

The reason you were getting that error is because unless you
specify otherwise, ax.bar will make the bottom of the bars at 0 -
which isn't an allowed date, hence the error. Change your bar
line to this (I also added align='center', but you can remove it
if you want):

#comment in

bot = times.min().round()
ax.bar(x, times-bot, bottom=bot, align='center')

ax.yaxis_date()
fig.autofmt_xdate()

plt.show()

best,

···

--
Paul Ivanov
314 address only used for lists, off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7

Hi Paul,

The reason you were getting that error is because unless you
specify otherwise, ax.bar will make the bottom of the bars at 0 -
which isn't an allowed date, hence the error. Change your bar
line to this (I also added align='center', but you can remove it
if you want):

Aha, OK that makes sense. Thank you. I think the point #3 in my
previous email about the "Ordinal must be >= 1" has all been about
what is or isn't allowed as a proper date.

So your example worked of course, but I am still not able to get my
real code to plot a bar chart. If I tell you what the format of the
data is, maybe you can help me.

I would like to plot dates (on x axis) versus time intervals (on y).
I have a list of dates and I have a two lists (self.data[0] and
self.data[1]), one of the start times ("bots") and one of the stop
times ("tops"). But when I go to plot it, and do this (based on your
code...for now leaving out the round() step):

bots = self.data[0]
tops = self.data[1]

bars = self.subplot.bar(self.final_dates, top-bot, bottom=bot, align='center')

I get the error:

TypeError: unsupported operand type(s) for -: 'list' and 'list'

Because I am trying to subtract the "bots" list from the "tops" list.
In the example code I gave, bot and times were not lists but were a
'numpy.ndarray' and a numpy.float64' object, respectfully, and I guess
the - operand can be used on them.

How can I structure my data such that this can work? (For some reason
I have not had nearly this much confusion with plotting lines, just
bars).

Thanks for all the help,
Che (CM)

C M, on 2011-01-27 13:56, wrote:

bars = self.subplot.bar(self.final_dates, top-bot, bottom=bot, align='center')

I get the error:

TypeError: unsupported operand type(s) for -: 'list' and 'list'

Because I am trying to subtract the "bots" list from the "tops" list.
In the example code I gave, bot and times were not lists but were a
'numpy.ndarray' and a numpy.float64' object, respectfully, and I guess
the - operand can be used on them.

How can I structure my data such that this can work? (For some reason
I have not had nearly this much confusion with plotting lines, just
bars).

Che,

just make a numpy array out of your two lists, and you'll be able
to subtract one from the other.

import numpy as np
top = np.array(top)
bot = np.array(bot)

best,

···

--
Paul Ivanov
314 address only used for lists, off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7

just make a numpy array out of your two lists, and you'll be able
to subtract one from the other.

import numpy as np
top = np.array(top)
bot = np.array(bot)

Thank you, Paul. That worked and I'm now able to display bar charts.
I appreciate it.

Best,
Che