Repository: scverse/scanpy

Issue:
All-zero genes show up as white columns in matrixplots if standard_scale='var' is given
Looks like this:

![image](https://user-images.githubusercontent.com/1140359/55589119-7ddf1f80-56fd-11e9-9496-a4da41ec2e50.png)

Not that it's wrong but it'd be prettier to show as regular as a regular grid.


Discussion:
Hmm, I think it’s a nice visual indicator that there’s just nothing at all. Don’t you agree?
I'm not sure really, it's also all white in other colormaps. The reason actually is a bug:

`mean_obs /= mean_obs.max(0).fillna(0)`

This doesn't fill NAs. It should be 

`mean_obs = (mean_obs / mean_obs.max(0)).fillna(0)`

😄 
Is is possible to give NAs their own color instead? I mean, they probably mean 0 in many cases, but not always, right?
@gokceneraslan Can you add a PR with the fix?
@flying-sheep Any good idea on how to set a color for NAs without having to add one more parameter to the visualizations (this problem is probably shared by matrixplot and dotplot)
heatmap passes additional kwargs to [`imshow`](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html) which accepts `cmap`. You can pass a [ColorMap](https://matplotlib.org/api/_as_gen/matplotlib.colors.Colormap.html#matplotlib.colors.Colormap) you’ve called [`set_bad`](https://matplotlib.org/api/_as_gen/matplotlib.colors.Colormap.html#matplotlib.colors.Colormap.set_bad) on.

Resolving patch:
diff --git a/scanpy/plotting/_anndata.py b/scanpy/plotting/_anndata.py
--- a/scanpy/plotting/_anndata.py
+++ b/scanpy/plotting/_anndata.py
@@ -830,7 +830,7 @@ def stacked_violin(adata, var_names, groupby=None, log=False, use_raw=None, num_
         obs_tidy = obs_tidy.div(obs_tidy.max(1), axis=0).fillna(0)
     elif standard_scale == 'var':
         obs_tidy -= obs_tidy.min(0)
-        obs_tidy /= obs_tidy.max(0).fillna(0)
+        obs_tidy = (obs_tidy / obs_tidy.max(0)).fillna(0)
     elif standard_scale is None:
         pass
     else:
@@ -1108,7 +1108,7 @@ def heatmap(adata, var_names, groupby=None, use_raw=None, log=False, num_categor
         obs_tidy = obs_tidy.div(obs_tidy.max(1), axis=0).fillna(0)
     elif standard_scale == 'var':
         obs_tidy -= obs_tidy.min(0)
-        obs_tidy /= obs_tidy.max(0).fillna(0)
+        obs_tidy = (obs_tidy / obs_tidy.max(0)).fillna(0)
     elif standard_scale is None:
         pass
     else:
@@ -1408,7 +1408,7 @@ def dotplot(adata, var_names, groupby=None, use_raw=None, log=False, num_categor
         mean_obs = mean_obs.div(mean_obs.max(1), axis=0).fillna(0)
     elif standard_scale == 'var':
         mean_obs -= mean_obs.min(0)
-        mean_obs /= mean_obs.max(0).fillna(0)
+        mean_obs = (mean_obs / mean_obs.max(0)).fillna(0)
     elif standard_scale is None:
         pass
     else:
@@ -1670,7 +1670,7 @@ def matrixplot(adata, var_names, groupby=None, use_raw=None, log=False, num_cate
         mean_obs = mean_obs.div(mean_obs.max(1), axis=0).fillna(0)
     elif standard_scale == 'var':
         mean_obs -= mean_obs.min(0)
-        mean_obs /= mean_obs.max(0).fillna(0)
+        mean_obs = (mean_obs / mean_obs.max(0)).fillna(0)
     elif standard_scale is None:
         pass
     else:


Test patch: