muon icon indicating copy to clipboard operation
muon copied to clipboard

Drawing embedding of variables shared in multiple mods will result in an error, even if axis=-1 is set.

Open liuzj039 opened this issue 2 years ago • 1 comments

Describe the bug Drawing umap graphs with the same variables in multiple mods will result in errors, even if axis=-1 is set.

To Reproduce

import muon as mu
import scanpy as sc
import pandas as pd

df = pd.DataFrame([[1,2,3]]*3, index=['a','b', 'c'], columns=['e','f','g'])
ad = sc.AnnData(df)
ad.obsm['X_umap'] = pd.DataFrame([[1,2]] * 3).values
md = mu.MuData({'aa': ad, 'bb': ad[:, :2]}, axis=-1)

print(md)
#MuData object with n_obs × n_vars = 3 × 3
#  2 modalities
#    aa:	3 x 3
#      obsm:	'X_umap'
#    bb:	3 x 2
#      obsm:	'X_umap'

mu.pl.embedding(md, 'aa:umap', color='e')

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-21-820ff8a24f5e> in <module>
----> 1 mu.pl.embedding(md, 'aa:umap', color='e')

~/softwares/anaconda3/lib/python3.8/site-packages/muon/_core/plot.py in embedding(data, basis, color, use_raw, layer, **kwargs)
    228                         )
    229                 x = fmod_adata.X.toarray() if issparse(fmod_adata.X) else fmod_adata.X
--> 230                 obs = obs.join(
    231                     pd.DataFrame(x, columns=mod_keys, index=fmod_adata.obs_names),
    232                     how="left",

~/softwares/anaconda3/lib/python3.8/site-packages/pandas/core/frame.py in join(self, other, on, how, lsuffix, rsuffix, sort)
   9097         5  K5  A5  NaN
   9098         """
-> 9099         return self._join_compat(
   9100             other, on=on, how=how, lsuffix=lsuffix, rsuffix=rsuffix, sort=sort
   9101         )

~/softwares/anaconda3/lib/python3.8/site-packages/pandas/core/frame.py in _join_compat(self, other, on, how, lsuffix, rsuffix, sort)
   9128                     sort=sort,
   9129                 )
-> 9130             return merge(
   9131                 self,
   9132                 other,

~/softwares/anaconda3/lib/python3.8/site-packages/pandas/core/reshape/merge.py in merge(left, right, how, on, left_on, right_on, left_index, right_index, sort, suffixes, copy, indicator, validate)
    119         validate=validate,
    120     )
--> 121     return op.get_result()
    122 
    123 

~/softwares/anaconda3/lib/python3.8/site-packages/pandas/core/reshape/merge.py in get_result(self)
    715         join_index, left_indexer, right_indexer = self._get_join_info()
    716 
--> 717         llabels, rlabels = _items_overlap_with_suffix(
    718             self.left._info_axis, self.right._info_axis, self.suffixes
    719         )

~/softwares/anaconda3/lib/python3.8/site-packages/pandas/core/reshape/merge.py in _items_overlap_with_suffix(left, right, suffixes)
   2306 
   2307     if not lsuffix and not rsuffix:
-> 2308         raise ValueError(f"columns overlap but no suffix specified: {to_rename}")
   2309 
   2310     def renamer(x, suffix):

ValueError: columns overlap but no suffix specified: Index(['e'], dtype='object')

System

  • muon 0.1.3

Additional context I noticed that in 0.1.3 there is support for setting the layers used by each mod in a dictionary way. But that doesn't get rid of the error.I suppose this is due to when iterating over each mod, if a variable is shared across multiple mods, it will result in the variable not being successfully joined. This may also be the reason why mudata emphasizes ensuring the uniqueness of variables in the mod as much as possible. But when a mod is only saving a subset of another mod (i.e. axis=-1), this error should be got around. I think it is possible to simply add a mod parameter, so that when iterating, it only iterates over the manually specified mod.

liuzj039 avatar Aug 18 '22 01:08 liuzj039

Thanks, @liuzj039.

That's a great point! I am still not sure about the proper interface for such alternative containers but maybe a mod=modality argument is good enough.

gtca avatar Sep 05 '22 16:09 gtca

This has been addressed locally by enabling the following syntax:

mu.pl.embedding(md, 'aa:umap', color='aa:e')

Please note this currently works only in mu.pl.embedding but we should be able to generalise it from there later.

gtca avatar Jan 29 '23 19:01 gtca