How to visualize 3 columns with boolean values?

@pitscher

To illustrate the boolean value of each position in a dataframe column I suggest the following idea:

Define a dataframe, df, and associate a Heatmap to z=df.values.T, i.e the rows in heatmap are the dataframe columns. Above this heatmap we are plotting a heatmap with the corresponding z of one row and len(df) columns, that contains the Boolean values resulted from a Boolean operation (and, or, not) between dataframe columns. The two heatmaps are represented in a subplot of two rows and 1 column:

import plotly.graph_objects as go
from  plotly.subplots import make_subplots
import pandas as pd
import numpy as np

def bool2string(A):
    #convert a binary array into an array of strings 'True' and 'False'
    S = np.empty(A.shape,  dtype=object)
    S[np.where(A)] = 'True'
    S[np.where(A==0)] = 'False'
    return S
clrs =[[0,  '#0000db'], #discrete colorscale to map 0 (False) to dark blue, and 1 (True) to red
       [0.5,  '#0000db'],
       [0.5, '#b10000'],
       [1, '#b10000']]
       
d = {'Artist': [ 1, 0, 1, 1, 1, 0,1, 1,0,1],
     'Institution': [0, 1, 0, 1,1,0,1, 1, 0, 1],
     'Unicorn': [1,0,1,0,0,1,0,0,0,1]}
df = pd.DataFrame(d)
fig = make_subplots(rows=2, cols=1, shared_xaxes=True)

fig.update_layout(yaxis_domain=[0.75, 1], yaxis2_domain=[0, 0.725]);# assign a smaller yaxis domain for the second heatmap
groups = list(df.columns)
A = df.values.T
fig.add_trace(go.Heatmap(z= A,  coloraxis='coloraxis', xgap=1, ygap=1, customdata = bool2string(A),
                           hovertemplate='%{customdata}<extra></extra>'), 2, 1)
# perform logical_and between A[0] and A[1] and convert the result to an array of ints;
# this array is then reshaped to a 2d array to be used as z in a Heatmap
and_01 = np.array(np.logical_and(A[0], A[1]), int).reshape(1,-1)


fig.add_trace(go.Heatmap(z= and_01,
                         coloraxis='coloraxis',
                          xgap=1, customdata = bool2string(and_01),
                          hovertemplate='%{customdata}<extra></extra>'
                           ), 1, 1)
fig.update_layout(title_text= 'Your title', title_x=0.5,
                  width=799, height=400, 
                  coloraxis=dict(colorscale=clrs, showscale=False),
                  yaxis2_tickvals=[0, 1,2], yaxis2_ticktext= groups, #yaxis2 is the yais of the heatap of 3 rows and 10 cols
                  yaxis2_autorange='reversed', 
                  yaxis_showticklabels=False, 
                  yaxis_title=f'{groups[0]}<br>and<br>{groups[1]}')

You can proceed similarly for A[0] and A[2], A[1] and A[2]
To calculate A[0] and A[1] and A[2] use chained np.logical_and:

and_012 = np.logical_and(np.logical_and(A[0], A[1]), A[2])
and_012  =  np.array(and_012, int).reshape(1,-1)