Repository: ydataai/ydata-profiling

Issue:
pandas_profiling modifies heavily matplotlib's rcParams
Thanks for this nice library.

Importing pandas_profiling modifies heavily matplotlib's rcParams. As a result it may render other plots unreadable (see for example
https://github.com/scikit-learn/scikit-learn/issues/17542 )

It would be much nicer if pandas_profiling set directly the desired tweaks on the visualizations that it creates, rather than modifying the global settings.

Another option would be to use the rc_context context manager: https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.rc_context.html It might be easier to code, but the drawback is that it would not be thread safe.

Thanks!


Discussion:
@GaelVaroquaux pandas_profiling indeed changes the defaults (https://github.com/pandas-profiling/pandas-profiling/blob/master/src/pandas_profiling/visualisation/pandas_profiling.mplstyle). This is legacy code, which I'm happy to remove if there is PR that achieves the same result without side effects.
Hi, I would like to take this.
@Jooong That's great. Feel free to make a PR or ask questions here and we'll help you further.

Resolving patch:
diff --git a/src/pandas_profiling/visualisation/context.py b/src/pandas_profiling/visualisation/context.py
new file mode 100644
--- /dev/null
+++ b/src/pandas_profiling/visualisation/context.py
@@ -0,0 +1,85 @@
+import contextlib
+import warnings
+
+import matplotlib
+import matplotlib.cbook
+import seaborn as sns
+from pandas.plotting import register_matplotlib_converters, deregister_matplotlib_converters
+from pkg_resources import resource_filename
+
+
+@contextlib.contextmanager
+def manage_matplotlib_context():
+    """Return a context manager for temporarily changing matplotlib unit registries and rcParams.
+    """
+    originalRcParams = matplotlib.rcParams.copy()
+
+    ## Credits for this style go to the ggplot and seaborn packages.
+    ##   We copied the style file to remove dependencies on the Seaborn package.
+    ##   Check it out, it's an awesome library for plotting
+    customRcParams = {
+        'patch.facecolor': '#348ABD',  # blue
+        'patch.antialiased': True,
+        'font.size': 10.0,
+        'figure.edgecolor': '0.50',
+
+        # Seaborn common parameters
+        'figure.facecolor': 'white',
+        'text.color': '.15',
+        'axes.labelcolor': '.15',
+        # legend.frameon: False
+        'legend.numpoints': 1,
+        'legend.scatterpoints': 1,
+        'xtick.direction': 'out',
+        'ytick.direction': 'out',
+        'xtick.color': '.15',
+        'ytick.color': '.15',
+        'axes.axisbelow': True,
+        'image.cmap': 'Greys',
+        'font.family': ['sans-serif'],
+        'font.sans-serif': ['Arial', 'Liberation Sans', 'Bitstream Vera Sans', 'sans-serif'],
+        'grid.linestyle': '-',
+        'lines.solid_capstyle': 'round',
+
+        # Seaborn darkgrid parameters
+        # .15 = dark_gray
+        # .8 = light_gray
+        'axes.grid': True,
+        'axes.facecolor': '#EAEAF2',
+        'axes.edgecolor': 'white',
+        'axes.linewidth': 0,
+        'grid.color': 'white',
+
+        # Seaborn notebook context
+        'figure.figsize': [8.0, 5.5],
+        'axes.labelsize': 11,
+        'axes.titlesize': 12,
+        'xtick.labelsize': 10,
+        'ytick.labelsize': 10,
+        'legend.fontsize': 10,
+
+        'grid.linewidth': 1,
+        'lines.linewidth': 1.75,
+        'patch.linewidth': .3,
+        'lines.markersize': 7,
+        'lines.markeredgewidth': 0,
+
+        'xtick.major.width': 1,
+        'ytick.major.width': 1,
+        'xtick.minor.width': .5,
+        'ytick.minor.width': .5,
+
+        'xtick.major.pad': 7,
+        'ytick.major.pad': 7
+    }
+
+    try:
+        register_matplotlib_converters()
+        matplotlib.rcParams.update(customRcParams)
+        sns.set_style(style="white")
+        yield
+    finally:
+        deregister_matplotlib_converters() # revert to original unit registries
+        with warnings.catch_warnings():
+            warnings.filterwarnings("ignore",category=matplotlib.cbook.mplDeprecation)
+            matplotlib.rcParams.update(originalRcParams) # revert to original rcParams
diff --git a/src/pandas_profiling/visualisation/missing.py b/src/pandas_profiling/visualisation/missing.py
--- a/src/pandas_profiling/visualisation/missing.py
+++ b/src/pandas_profiling/visualisation/missing.py
@@ -4,6 +4,7 @@
 from missingno import missingno
 
 from pandas_profiling.config import config
+from pandas_profiling.visualisation.context import manage_matplotlib_context
 from pandas_profiling.visualisation.utils import hex_to_rgb, plot_360_n0sc0pe
 
 
@@ -31,6 +32,7 @@ def get_font_size(data):
     return font_size
 
 
+@manage_matplotlib_context()
 def missing_matrix(data: pd.DataFrame) -> str:
     """Generate missing values matrix plot
 
@@ -53,6 +55,7 @@ def missing_matrix(data: pd.DataFrame) -> str:
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def missing_bar(data: pd.DataFrame) -> str:
     """Generate missing values bar plot.
 
@@ -77,6 +80,7 @@ def missing_bar(data: pd.DataFrame) -> str:
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def missing_heatmap(data: pd.DataFrame) -> str:
     """Generate missing values heatmap plot.
 
@@ -113,6 +117,7 @@ def missing_heatmap(data: pd.DataFrame) -> str:
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def missing_dendrogram(data: pd.DataFrame) -> str:
     """Generate a dendrogram plot for missing values.
 
diff --git a/src/pandas_profiling/visualisation/plot.py b/src/pandas_profiling/visualisation/plot.py
--- a/src/pandas_profiling/visualisation/plot.py
+++ b/src/pandas_profiling/visualisation/plot.py
@@ -9,15 +9,10 @@
 import seaborn as sns
 from matplotlib.colors import LinearSegmentedColormap
 from matplotlib.patches import Patch
-from pandas.plotting import register_matplotlib_converters
-from pkg_resources import resource_filename
 
 from pandas_profiling.config import config
 from pandas_profiling.visualisation.utils import plot_360_n0sc0pe
-
-register_matplotlib_converters()
-matplotlib.style.use(resource_filename(__name__, "pandas_profiling.mplstyle"))
-sns.set_style(style="white")
+from pandas_profiling.visualisation.context import manage_matplotlib_context
 
 
 def _plot_histogram(
@@ -47,6 +42,7 @@ def _plot_histogram(
     return plot
 
 
+@manage_matplotlib_context()
 def histogram(
     series: np.ndarray, series_description: dict, bins: Union[int, np.ndarray]
 ) -> str:
@@ -67,6 +63,7 @@ def histogram(
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def mini_histogram(
     series: np.ndarray, series_description: dict, bins: Union[int, np.ndarray]
 ) -> str:
@@ -134,6 +131,7 @@ def get_correlation_font_size(n_labels) -> Optional[int]:
     return font_size
 
 
+@manage_matplotlib_context()
 def correlation_matrix(data: pd.DataFrame, vmin: int = -1) -> str:
     """Plot image of a matrix correlation.
 
@@ -177,6 +175,7 @@ def correlation_matrix(data: pd.DataFrame, vmin: int = -1) -> str:
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def scatter_complex(series: pd.Series) -> str:
     """Scatter plot (or hexbin plot) from a series of complex values
 
@@ -205,6 +204,7 @@ def scatter_complex(series: pd.Series) -> str:
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def scatter_series(series, x_label="Width", y_label="Height") -> str:
     """Scatter plot (or hexbin plot) from one series of sequences with length 2
 
@@ -233,6 +233,7 @@ def scatter_series(series, x_label="Width", y_label="Height") -> str:
     return plot_360_n0sc0pe(plt)
 
 
+@manage_matplotlib_context()
 def scatter_pairwise(series1, series2, x_label, y_label) -> str:
     """Scatter plot (or hexbin plot) from two series
 


Test patch: