Henri
Henri

Reputation: 1235

Table in Matplotlib, can't get two columns?

I'm struggling with tables for matplotlib (blume). The table is for an automation project that will produce 22 different maps. The code below produce a table with 49 rows. Some figures will only have 6 rows. When the number of rows exceeds 25 I would like to use two columns.

import pandas as pd
import matplotlib.pyplot as plt
from blume.table import table

# Dataframe

df=pd.DataFrame({'nr': [ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
       35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
             'KnNamn': ['Härryda', 'Partille', 'Öckerö', 'Stenungsund', 'Tjörn', 'Orust',
       'Sotenäs', 'Munkedal', 'Tanum', 'Dals-Ed', 'Färgelanda', 'Ale',
       'Lerum', 'Vårgårda', 'Bollebygd', 'Grästorp', 'Essunga',
       'Karlsborg', 'Gullspång', 'Tranemo', 'Bengtsfors', 'Mellerud',
       'Lilla Edet', 'Mark', 'Svenljunga', 'Herrljunga', 'Vara', 'Götene',
       'Tibro', 'Töreboda', 'Göteborg', 'Mölndal', 'Kungälv', 'Lysekil',
       'Uddevalla', 'Strömstad', 'Vänersborg', 'Trollhättan', 'Alingsås',
       'Borås', 'Ulricehamn', 'Åmål', 'Mariestad', 'Lidköping', 'Skara',
       'Skövde', 'Hjo', 'Tidaholm', 'Falköping'],
             'rel': [0.03650425, 0.05022105, 0.03009109, 0.03966735, 0.02793296,
       0.03690838, 0.04757161, 0.05607283, 0.0546372 , 0.05452821,
       0.06640368, 0.04252673, 0.03677577, 0.05385784, 0.0407173 ,
       0.04024881, 0.05613226, 0.04476127, 0.08543165, 0.04070175,
       0.09281077, 0.08711656, 0.06111578, 0.04564958, 0.05058988,
       0.04618078, 0.04640402, 0.04826498, 0.08514253, 0.07799246,
       0.07829886, 0.04249149, 0.03909206, 0.06835601, 0.08027622,
       0.07087295, 0.09013876, 0.1040369 , 0.05004451, 0.06584845,
       0.04338739, 0.10570863, 0.0553109 , 0.05024871, 0.06531729,
       0.05565605, 0.05041816, 0.04885198, 0.07954831]})

# Table
fig,ax = plt.subplots(1, figsize=(10, 7))
    
val =[]

ax.axis('off')

for i, j, k in zip(df.nr, df.KnNamn, df.rel):
    k = k*100
    k = round(k,2)
    k= (str(k) + ' %')
    temp=str(i)+'. ' +str(j)+': ' + str(k)
    val.append(temp)
    
val=[[el] for el in val]
#val=val[0] + val[1]

tab=table(ax,cellText=val, 
                #rowLabels=row_lab, 
                colLabels=['Relativ arbetslöshet'], loc='left', colWidths=[0.3], cellLoc='left')

plt.show()

As I understands it, if I want a table with two columns, my val object should be structured in a different way. In the case above, val is a nested list with 49 lists inside. I need to merge lists, I figure. I tried this pairwise for loop but that didn't work with range?

I'm sure there is a simple solution to this problem I have. Help would be much appreciated.

for i, j in zip(range(len(val)), range(len(val))[1:] + range(len(val))[:1]):
 print(i, j)
    

Upvotes: 0

Views: 477

Answers (1)

furas
furas

Reputation: 142641

I don't know if it is what you need but you could use zip() or better itertools.zip_longest() with val[:25], val[25:]

two_columns = []

for col1, col2 in itertools.zip_longest(values[:25], values[25:], fillvalue=''):
    #print(f'{col1:25} | {col2}')
    two_columns.append([col1, col2])

Full working example

import pandas as pd
import matplotlib.pyplot as plt
from blume.table import table
import itertools

df = pd.DataFrame({
    'nr': [
        1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
    ],
    'KnNamn': [
        'Härryda', 'Partille', 'Öckerö', 'Stenungsund', 'Tjörn', 'Orust',
        'Sotenäs', 'Munkedal', 'Tanum', 'Dals-Ed', 'Färgelanda', 'Ale',
        'Lerum', 'Vårgårda', 'Bollebygd', 'Grästorp', 'Essunga',
        'Karlsborg', 'Gullspång', 'Tranemo', 'Bengtsfors', 'Mellerud',
        'Lilla Edet', 'Mark', 'Svenljunga', 'Herrljunga', 'Vara', 'Götene',
        'Tibro', 'Töreboda', 'Göteborg', 'Mölndal', 'Kungälv', 'Lysekil',
        'Uddevalla', 'Strömstad', 'Vänersborg', 'Trollhättan', 'Alingsås',
        'Borås', 'Ulricehamn', 'Åmål', 'Mariestad', 'Lidköping', 'Skara',
        'Skövde', 'Hjo', 'Tidaholm', 'Falköping'
    ],
    'rel': [
        0.03650425, 0.05022105, 0.03009109, 0.03966735, 0.02793296,
        0.03690838, 0.04757161, 0.05607283, 0.0546372 , 0.05452821,
        0.06640368, 0.04252673, 0.03677577, 0.05385784, 0.0407173 ,
        0.04024881, 0.05613226, 0.04476127, 0.08543165, 0.04070175,
        0.09281077, 0.08711656, 0.06111578, 0.04564958, 0.05058988,
        0.04618078, 0.04640402, 0.04826498, 0.08514253, 0.07799246,
        0.07829886, 0.04249149, 0.03909206, 0.06835601, 0.08027622,
        0.07087295, 0.09013876, 0.1040369 , 0.05004451, 0.06584845,
        0.04338739, 0.10570863, 0.0553109 , 0.05024871, 0.06531729,
        0.05565605, 0.05041816, 0.04885198, 0.07954831
    ]
})

# df = df[:25]  # test for 25 rows

# ---

fig, ax = plt.subplots(1, figsize=(10, 7))
ax.axis('off')

# --- values ---
    
#values = []

#for number, name, rel in zip(df.nr, df.KnNamn, df.rel):
#    text = f'{number}. {name}: {rel*100:.2} %'
#    values.append(text)

values = df.apply(lambda row: f'{row["nr"]}. {row["KnNamn"]}: {row["rel"]*100:.2} %', axis=1).values

# --- columns ---

if len(values) > 25:
    two_columns = []
    
    for col1, col2 in itertools.zip_longest(values[:25], values[25:], fillvalue=''):
        #print(f'{col1:25} | {col2}')
        two_columns.append([col1, col2])

    tab = table(ax, cellText=two_columns, 
            #rowLabels=row_lab, 
            colLabels=['Col1', 'Col2'], colWidths=[0.3, 0.3], loc=-100, cellLoc='left')
else:
    one_column = [[item] for item in values]
    
    tab = table(ax, cellText=one_column, 
            #rowLabels=row_lab, 
            colLabels=['Col1'], colWidths=[0.3], loc=-100, cellLoc='left')
    
# --- plot ---    

plt.show()

Result:

enter image description here


EDIT:

More universal version which can create many columns.

Example automatically create 3 columns for ROWS = 20.

import pandas as pd
import matplotlib.pyplot as plt
from blume.table import table
import itertools

df = pd.DataFrame({
    'nr': [
        1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
    ],
    'KnNamn': [
        'Härryda', 'Partille', 'Öckerö', 'Stenungsund', 'Tjörn', 'Orust',
        'Sotenäs', 'Munkedal', 'Tanum', 'Dals-Ed', 'Färgelanda', 'Ale',
        'Lerum', 'Vårgårda', 'Bollebygd', 'Grästorp', 'Essunga',
        'Karlsborg', 'Gullspång', 'Tranemo', 'Bengtsfors', 'Mellerud',
        'Lilla Edet', 'Mark', 'Svenljunga', 'Herrljunga', 'Vara', 'Götene',
        'Tibro', 'Töreboda', 'Göteborg', 'Mölndal', 'Kungälv', 'Lysekil',
        'Uddevalla', 'Strömstad', 'Vänersborg', 'Trollhättan', 'Alingsås',
        'Borås', 'Ulricehamn', 'Åmål', 'Mariestad', 'Lidköping', 'Skara',
        'Skövde', 'Hjo', 'Tidaholm', 'Falköping'
    ],
    'rel': [
        0.03650425, 0.05022105, 0.03009109, 0.03966735, 0.02793296,
        0.03690838, 0.04757161, 0.05607283, 0.0546372 , 0.05452821,
        0.06640368, 0.04252673, 0.03677577, 0.05385784, 0.0407173 ,
        0.04024881, 0.05613226, 0.04476127, 0.08543165, 0.04070175,
        0.09281077, 0.08711656, 0.06111578, 0.04564958, 0.05058988,
        0.04618078, 0.04640402, 0.04826498, 0.08514253, 0.07799246,
        0.07829886, 0.04249149, 0.03909206, 0.06835601, 0.08027622,
        0.07087295, 0.09013876, 0.1040369 , 0.05004451, 0.06584845,
        0.04338739, 0.10570863, 0.0553109 , 0.05024871, 0.06531729,
        0.05565605, 0.05041816, 0.04885198, 0.07954831
    ]
})

#df = df[:25]  # test for 25 rows

# ---

fig, ax = plt.subplots(1, figsize=(10, 7))
ax.axis('off')

# --- values ---

def convert(row):
    return f'{row["nr"]}. {row["KnNamn"]}: {row["rel"]*100:.2} %'

values = df.apply(convert, axis=1).values

# --- columns ---

ROWS = 20
#ROWS = 25

columns = []
for idx in range(0, len(values), ROWS):
    columns.append(values[idx:idx+ROWS])

columns_widths = [0.3] * len(columns)
columns_labels = [f'Col{i}' for i in range(1, len(columns)+1)]

rows = list(itertools.zip_longest(*columns, fillvalue=''))

# --- plot ---

tab = table(ax,
            cellText=rows, 
            #rowLabels=row_lab, 
            colLabels=columns_labels,
            colWidths=columns_widths,
            loc=-100,
            cellLoc='left')

plt.show()

Result:

enter image description here

Upvotes: 1

Related Questions