class_docstr: Legend guide
  
  Parameters
  ----------
  nrow : int, default=None
      Number of rows of legends.
  ncol : int, default=None
      Number of columns of legends.
  byrow : bool, default=False
      Whether to fill the legend row-wise or column-wise.
  keywidth : float, default=None
      Width of the legend key.
  keyheight : float, default=None
      Height of the legend key.
  kwargs : dict
      Parameters passed on to [](`~plotnine.guides.guide`).
code: def _calculate_rows_and_cols(self) -> TupleInt2:
      nrow, ncol = -1, -1
      nbreak = len(self.key)
  
      if hasattr(self, "nrow"):
          nrow = self.nrow
  
      if hasattr(self, "ncol"):
          ncol = self.ncol
  
      if nrow != -1 and ncol != -1:
          if nrow * ncol < nbreak:
              raise PlotnineError(
                  "nrow x ncol need to be larger "
                  "than the number of breaks"
              )
          return nrow, ncol
  
      if nrow == -1 and ncol == -1:
          if self.direction == "horizontal":
              nrow = int(np.ceil(nbreak / 5))
          else:
              ncol = int(np.ceil(nbreak / 20))
  
      if nrow == -1:
          nrow = int(np.ceil(nbreak / ncol))
      elif ncol == -1:
          ncol = int(np.ceil(nbreak / nrow))
  
      return nrow, ncol
  
imports: from __future__ import annotations
  import hashlib
  import types
  import typing
  from contextlib import suppress
  from itertools import islice
  from warnings import warn
  import numpy
  import pandas
  from .._utils import SIZE_FACTOR, remove_missing
  from ..exceptions import PlotnineError, PlotnineWarning
  from ..geoms import geom_text
  from ..mapping.aes import rename_aesthetics
  from .guide import guide
label_desc: Use image node_id 4 for calling the guide_legend obj's underlying member method code with example usage: obj._calculate_rows_and_cols() and returns: nrow,  ncol, nrow,  ncol