Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I coordinate colors between seaborn and networkx?

I'm trying to coordinate colors on a networkx network chart with the colors on seaborn charts. When I use the same color pallet (Dark2) and same group ids, the two plots still come out different. To be clear, the nodes in group 0 should be the same as the bars in group 0. The same should hold true for groups 1 & 2. Here is the chart I get when I run the code below, showing that the colors don't remain consistent: example chart

When I run the code below, in the network plot, the colors for group 0 are the same as they are in the count plot. But groups 1 and 2 change colors between the network plot and the count plot. Does anyone know how to coordinate the colors?

I have compared the color mappings in plt.cm.Dark2.colors to the mappings in sns.color_palette('Dark2', 3) and they appear to be the same (besides the fact that sns only includes the first 3 colors.

Also worth noting, seaborn is following the expected order of colors, networkx is not.

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import seaborn as sns

# create dataframe of connections
df = pd.DataFrame({ 'from':['A', 'B', 'C','A'], 'to':['D', 'A', 'E','C']})

# create graph
G = nx.Graph()
for i, r in df.iterrows():
    G.add_edge(r['from'], r['to'])

# create data frame mapping nodes to groups
groups_df = pd.DataFrame()

for i in G.nodes():
    if i in 'AD':
        group = 0
    elif i in 'BC':
        group = 1
    else:
        group = 2

    groups_df.loc[i, 'group'] = group

# make sure it's in same order as nodes of graph
groups_df = groups_df.reindex(G.nodes())

# create node node and count chart where color is group id
fig, ax = plt.subplots(ncols=2)
nx.draw(G, with_labels=True, node_color=groups_df['group'], cmap=plt.cm.Dark2, ax=ax[0])

sns.countplot('index', data=groups_df.reset_index(), palette='Dark2', hue='group', ax=ax[1])
like image 412
Tony B Avatar asked Dec 19 '19 19:12

Tony B


Video Answer


1 Answers

networkx distributes the values equally over the colors of the colormap. Since it apparently cannot take in a norm (which would be the usual way to tackle this), you would need to create a new colormap with only the colors you're interested in.

cmap = ListedColormap(plt.cm.Dark2(np.arange(3)))

Also, seaborn will desaturate the colors to be used, so to get the same colors as with the colormap, you need to set saturation=1 in the seaborn call.

import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import seaborn as sns

# create dataframe of connections
df = pd.DataFrame({ 'from':['A', 'B', 'C','A'], 'to':['D', 'A', 'E','C']})
# create graph
G = nx.Graph()
for i, r in df.iterrows():
    G.add_edge(r['from'], r['to'])

# create data frame mapping nodes to groups
groups_df = pd.DataFrame()

for i in G.nodes():
    if i in 'AD':
        group = 0
    elif i in 'BC':
        group = 1
    else:
        group = 2
    groups_df.loc[i, 'group'] = group

# make sure it's in same order as nodes of graph
groups_df = groups_df.reindex(G.nodes())

# create node node and count chart where color is group id
fig, ax = plt.subplots(ncols=2)

# create new colormap with only the first 3 colors from Dark2
cmap = ListedColormap(plt.cm.Dark2(np.arange(3)))
nx.draw(G, with_labels=True, node_color=groups_df['group'], cmap=cmap, ax=ax[0])

sns.countplot('index', data=groups_df.reset_index(), palette=cmap.colors, hue='group', ax=ax[1], saturation=1)

plt.show()

enter image description here

like image 150
ImportanceOfBeingErnest Avatar answered Sep 30 '22 03:09

ImportanceOfBeingErnest