Skip to content

what do we learn when we make colormaps from dataframes¤

    import pandas, numpy, toolz.curried as toolz

we'll begin with a small linear domain of values between 0..1.

    domain = numpy.linspace(0, 1, 11)

we'll focus on primary color components to start. from the primary components we can make a lot of colors. we combine the domain with empty values, to create triplets that will become our color.

    triples = list(map(numpy.array, zip(domain, domain*0, domain*0)))

we'll start with making red, with a focus on rgb values, as a series of triples between 0..255.

    red = pandas.Series(triples).apply(numpy.array).mul(255)
    red
0                    [0.0, 0.0, 0.0]
1                   [25.5, 0.0, 0.0]
2                   [51.0, 0.0, 0.0]
3      [76.50000000000001, 0.0, 0.0]
4                  [102.0, 0.0, 0.0]
5                  [127.5, 0.0, 0.0]
6     [153.00000000000003, 0.0, 0.0]
7     [178.50000000000003, 0.0, 0.0]
8                  [204.0, 0.0, 0.0]
9                  [229.5, 0.0, 0.0]
10                 [255.0, 0.0, 0.0]
dtype: object
    def rgb(x): "format a pandas cells"; return "font-size: 0px; background-color: rgb(" + ", ".join(
            map(str, x)
        ) + ");"

why are we calling this value red?

because we can explicitly the format for each cell and (255, 0, 0) is completely red.

    red.to_frame("red").T.applymap(rgb)
0 1 2 3 4 5 6 7 8 9 10
red font-size: 0px; background-color: rgb(0.0, 0.0... font-size: 0px; background-color: rgb(25.5, 0.... font-size: 0px; background-color: rgb(51.0, 0.... font-size: 0px; background-color: rgb(76.50000... font-size: 0px; background-color: rgb(102.0, 0... font-size: 0px; background-color: rgb(127.5, 0... font-size: 0px; background-color: rgb(153.0000... font-size: 0px; background-color: rgb(178.5000... font-size: 0px; background-color: rgb(204.0, 0... font-size: 0px; background-color: rgb(229.5, 0... font-size: 0px; background-color: rgb(255.0, 0...

with a small change to code in the cell above, we can indeed colorize our table.

    red.to_frame("red").T.style.applymap(rgb)
  0 1 2 3 4 5 6 7 8 9 10
red [0. 0. 0.] [25.5 0. 0. ] [51. 0. 0.] [76.5 0. 0. ] [102. 0. 0.] [127.5 0. 0. ] [153. 0. 0.] [178.5 0. 0. ] [204. 0. 0.] [229.5 0. 0. ] [255. 0. 0.]

green and blue are a shift of the indices in the triple.

    @toolz.curry
    def shift(n, x):
        return numpy.concatenate([x[n:], x[:n]])

with shift(1) for blue, and shift(2) for green we can construct a composite dataframe with all of our rgb colorvalues ...

    colors = "red blue green".split()
    df = pandas.concat({
        c: red.apply(shift(i)).rename(c) for i, c in enumerate(colors)
    }, axis=1).T; df
0 1 2 3 4 5 6 7 8 9 10
red [0.0, 0.0, 0.0] [25.5, 0.0, 0.0] [51.0, 0.0, 0.0] [76.50000000000001, 0.0, 0.0] [102.0, 0.0, 0.0] [127.5, 0.0, 0.0] [153.00000000000003, 0.0, 0.0] [178.50000000000003, 0.0, 0.0] [204.0, 0.0, 0.0] [229.5, 0.0, 0.0] [255.0, 0.0, 0.0]
blue [0.0, 0.0, 0.0] [0.0, 0.0, 25.5] [0.0, 0.0, 51.0] [0.0, 0.0, 76.50000000000001] [0.0, 0.0, 102.0] [0.0, 0.0, 127.5] [0.0, 0.0, 153.00000000000003] [0.0, 0.0, 178.50000000000003] [0.0, 0.0, 204.0] [0.0, 0.0, 229.5] [0.0, 0.0, 255.0]
green [0.0, 0.0, 0.0] [0.0, 25.5, 0.0] [0.0, 51.0, 0.0] [0.0, 76.50000000000001, 0.0] [0.0, 102.0, 0.0] [0.0, 127.5, 0.0] [0.0, 153.00000000000003, 0.0] [0.0, 178.50000000000003, 0.0] [0.0, 204.0, 0.0] [0.0, 229.5, 0.0] [0.0, 255.0, 0.0]

that may be stylized using the df.style feature

    df.style.applymap(rgb)
  0 1 2 3 4 5 6 7 8 9 10
red [0. 0. 0.] [25.5 0. 0. ] [51. 0. 0.] [76.5 0. 0. ] [102. 0. 0.] [127.5 0. 0. ] [153. 0. 0.] [178.5 0. 0. ] [204. 0. 0.] [229.5 0. 0. ] [255. 0. 0.]
blue [0. 0. 0.] [ 0. 0. 25.5] [ 0. 0. 51.] [ 0. 0. 76.5] [ 0. 0. 102.] [ 0. 0. 127.5] [ 0. 0. 153.] [ 0. 0. 178.5] [ 0. 0. 204.] [ 0. 0. 229.5] [ 0. 0. 255.]
green [0. 0. 0.] [ 0. 25.5 0. ] [ 0. 51. 0.] [ 0. 76.5 0. ] [ 0. 102. 0.] [ 0. 127.5 0. ] [ 0. 153. 0.] [ 0. 178.5 0. ] [ 0. 204. 0.] [ 0. 229.5 0. ] [ 0. 255. 0.]

from our df containing a primary palette we can build a secondary palette.

    secondary =     pandas.concat([    
        df.loc["red"].add(df.loc["blue"]).rename("violet"),
        df.loc["red"].add(df.loc["green"]).rename("yellow"),
        df.loc["blue"].add(df.loc["green"]).rename("cyan")
    ], axis=1).T; secondary.style.applymap(rgb)
  0 1 2 3 4 5 6 7 8 9 10
violet [0. 0. 0.] [25.5 0. 25.5] [51. 0. 51.] [76.5 0. 76.5] [102. 0. 102.] [127.5 0. 127.5] [153. 0. 153.] [178.5 0. 178.5] [204. 0. 204.] [229.5 0. 229.5] [255. 0. 255.]
yellow [0. 0. 0.] [25.5 25.5 0. ] [51. 51. 0.] [76.5 76.5 0. ] [102. 102. 0.] [127.5 127.5 0. ] [153. 153. 0.] [178.5 178.5 0. ] [204. 204. 0.] [229.5 229.5 0. ] [255. 255. 0.]
cyan [0. 0. 0.] [ 0. 25.5 25.5] [ 0. 51. 51.] [ 0. 76.5 76.5] [ 0. 102. 102.] [ 0. 127.5 127.5] [ 0. 153. 153.] [ 0. 178.5 178.5] [ 0. 204. 204.] [ 0. 229.5 229.5] [ 0. 255. 255.]

they can all be recombined together on their respective order.

    all = pandas.concat([df, secondary]).loc[
        "red violet blue cyan green yellow".split()]

    all.style.applymap(rgb)
  0 1 2 3 4 5 6 7 8 9 10
red [0. 0. 0.] [25.5 0. 0. ] [51. 0. 0.] [76.5 0. 0. ] [102. 0. 0.] [127.5 0. 0. ] [153. 0. 0.] [178.5 0. 0. ] [204. 0. 0.] [229.5 0. 0. ] [255. 0. 0.]
violet [0. 0. 0.] [25.5 0. 25.5] [51. 0. 51.] [76.5 0. 76.5] [102. 0. 102.] [127.5 0. 127.5] [153. 0. 153.] [178.5 0. 178.5] [204. 0. 204.] [229.5 0. 229.5] [255. 0. 255.]
blue [0. 0. 0.] [ 0. 0. 25.5] [ 0. 0. 51.] [ 0. 0. 76.5] [ 0. 0. 102.] [ 0. 0. 127.5] [ 0. 0. 153.] [ 0. 0. 178.5] [ 0. 0. 204.] [ 0. 0. 229.5] [ 0. 0. 255.]
cyan [0. 0. 0.] [ 0. 25.5 25.5] [ 0. 51. 51.] [ 0. 76.5 76.5] [ 0. 102. 102.] [ 0. 127.5 127.5] [ 0. 153. 153.] [ 0. 178.5 178.5] [ 0. 204. 204.] [ 0. 229.5 229.5] [ 0. 255. 255.]
green [0. 0. 0.] [ 0. 25.5 0. ] [ 0. 51. 0.] [ 0. 76.5 0. ] [ 0. 102. 0.] [ 0. 127.5 0. ] [ 0. 153. 0.] [ 0. 178.5 0. ] [ 0. 204. 0.] [ 0. 229.5 0. ] [ 0. 255. 0.]
yellow [0. 0. 0.] [25.5 25.5 0. ] [51. 51. 0.] [76.5 76.5 0. ] [102. 102. 0.] [127.5 127.5 0. ] [153. 153. 0.] [178.5 178.5 0. ] [204. 204. 0.] [229.5 229.5 0. ] [255. 255. 0.]