1

I am trying to plot a bar diagram using input from a .csv file.

My input file contains several columns with sample names and data and also a column with the colour of my sample. This column contains strings, such as 'w' meaning white, 'b' meaning brown and so forth. Each line contains values for a different sample.

Now I want the bar for each sample to have the colour specified in the colour column.

My code looks a bit like this:

import numpy as np
import matplotlib.pyplot as plt

results_dtype=np.dtype([('name', 'S100'), ('colour', 'S10'),
('data_this', 'float64'), ('data_that', 'float64'), ...])


data = np.genfromtxt('C:/data.csv', delimiter = ',', dtype =results_dtype, filling_values=np.nan, skip_header=1)

colours = {'w':'#FFFFFF',
'y':'#ffff00',
'b':'#cc8033',
'p':'#CC79A7'}

fig = plt.figure()
plt.bar(np.arange(len(data)), data['data_this'], bottom=data['data_that'], align='center', color=colours[data['colour']])
plt.xticks(np.arange(len(data)), data['name'], rotation='vertical')
plt.show()

The error message I get is the following:

unhashable type: 'numpy.ndarray' (pointing to the plt.bar(...) line).

It sounds like I'm calling the dictionary the wrong way or something along those lines but I can't figure out how to do it properly.

I hope, this is explains what I'm trying to do.

1
  • it just gives me the same error message Commented Jan 27, 2016 at 16:31

1 Answer 1

2

Python's dicts can only be indexed with a single key. They don't allow "vectorized" indexing.

Let's use a simplified example that gives the same error:

import numpy as np

lookup = {'a':1, 'b':2, 'c':3}
values = np.array(['a', 'b', 'c', 'c', 'a', 'b', 'a'])
data = lookup[values]

Which yields:

TypeError                                 Traceback (most recent call last)
<ipython-input-71-7d8663a08b8d> in <module>()
      1 lookup = {'a':1, 'b':2, 'c':3}
      2 values = np.array(['a', 'b', 'c', 'c', 'a', 'b', 'a'])
----> 3 data = lookup[values]

TypeError: unhashable type: 'numpy.ndarray'

The exact error is because we're trying to use a mutable type as a key to the dict. There are sequences (e.g. tuples) that you could use as a key, but they still wouldn't work in the way that you want them to.

Therefore, instead of using a sequence of keys such as data = lookup[values], you'll need to use a list comprehension:

data = [lookup[item] for item in values]

Putting this back into your original example:

import numpy as np
import matplotlib.pyplot as plt

results_dtype=np.dtype([('name', 'S100'), ('colour', 'S10'),
('data_this', 'float64'), ('data_that', 'float64'), ...])


data = np.genfromtxt('C:/data.csv', delimiter = ',', dtype=results_dtype, 
                     filling_values=np.nan, skip_header=1)

colours = {'w':'#FFFFFF',
           'y':'#ffff00',
           'b':'#cc8033',
           'p':'#CC79A7'}

color = [colours[item] for item in data['colour']]

fig = plt.figure()
plt.bar(np.arange(len(data)), data['data_this'], bottom=data['data_that'],  
        align='center', color=color)
plt.xticks(np.arange(len(data)), data['name'], rotation='vertical')
plt.show()
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for your quick reply! Problem solved and I'm happy! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.