1

I'm trying to visualize a sorted table (sorted on a column). My ideal result should be something like

visualization of a sorted table

Any suggestion on how to reach this goal with matplotlib?

I'have already tried with suggestions given here and here but I'm looking for something fancier like that in the attached image.

Thanks in advance,

Community
  • 1
  • 1
Luca Jokull
  • 181
  • 2
  • 9
  • I don't think matplotlib supports this kind of plots. – cel Oct 23 '15 at 09:23
  • Welcome to SO. I answered your question, even though it doesn't really comply with the standards of SO: SO is not a coding service, so usually you will not get answers unless you show what you have tried yourself (yes, post your code) and where you failed. – hitzg Oct 23 '15 at 13:23

1 Answers1

0

Matplotlib does not support this directly, but it is fairly easy to replicate the plot that you have linked to.

The function below does something similar given a 2d array of data. It can be sorted or not, the function doesn't really care.

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np

def sorted_table_plot(data, labels, categories, cmap=None, ax=None):

    # check if an axes was supplied
    if ax is None:
        ax = plt.gca()

    # check if a colormap was supplied
    if cmap is None:
        cmap = plt.cm.jet

    # generate the grid arrays with the coordinates for the annotations
    yy, xx = np.mgrid[:data.shape[0], :data.shape[1]]
    x = xx.flatten()
    y = yy.flatten()
    d = data.flatten()

    # a norm object which we will use with the colorbar
    norm = plt.Normalize(d.min(), d.max())

    # iterate over the data points and draw the labels
    for di, xi, yi in zip(d, x, y):
        color = cmap(norm(di))
        hsv = mcolors.rgb_to_hsv(color[:3])
        fc = 'w' if hsv[2] < 0.7 else 'k'
        ax.annotate(str(di), xy=(xi,yi), xycoords="data",
                va="center", ha="center", color=fc,
                bbox=dict(boxstyle="circle", fc=color))

    # iteratve over all the appearing values and draw the lines
    for i in np.unique(data):
        xi, yi = x[d==i], y[d==i]
        idx = np.argsort(xi)
        plt.plot(xi[idx], yi[idx], color=plt.cm.jet(norm(i)), lw=2)

    # add the axes labels
    ax.set_xticks(xx[0,:])
    ax.set_xticklabels(categories)
    ax.set_yticks(yy[:,0])
    ax.set_yticklabels(labels)

    # adjust the axes ranges
    ax.set_xlim(xx[0,0] - 0.5, xx[-1,-1] + 0.5)
    ax.set_ylim(yy[-1,-1] + 0.5, yy[0,0] - 0.5)

Now, you can simply call it on a data array. In the following I created a random array, since you didn't care to supply an example data set.

# fix the seed for reproducability
np.random.seed(2)

# create random data
data = np.tile(np.arange(1,8), (3,1)).T
labels = map(lambda x: 'label ' + str(x), data[:,1])
categories = map(lambda x: 'cat ' + str(x), np.arange(data.shape[1])+1)
for i in range(1,data.shape[1]):
    # shuffle all but the first column
    np.random.shuffle(data[:,i])

# call the function and show the plot
sorted_table_plot(data, labels, categories)
plt.show()

Result:

enter image description here

hitzg
  • 12,133
  • 52
  • 54