code: def complete(
      df: pd.DataFrame,
      *columns: Any,
      sort: bool = False,
      by: Optional[Union[list, str]] = None,
      fill_value: Optional[Union[Dict, Any]] = None,
      explicit: bool = True,
  ) -> pd.DataFrame:
      """Complete a data frame with missing combinations of data.
  
      It is modeled after tidyr's `complete` function, and is a wrapper around
      [`expand_grid`][janitor.functions.expand_grid.expand_grid], `pd.merge`
      and `pd.fillna`. In a way, it is the inverse of `pd.dropna`, as it exposes
      implicitly missing rows.
  
      Combinations of column names or a list/tuple of column names, or even a
      dictionary of column names and new values are possible.
      If a dictionary is passed,
      the user is required to ensure that the values are unique 1-D arrays.
      The keys in a dictionary must be present in the dataframe.
  
      Examples:
          >>> import pandas as pd
          >>> import janitor
          >>> import numpy as np
          >>> df = pd.DataFrame(
          ...     {
          ...         "Year": [1999, 2000, 2004, 1999, 2004],
          ...         "Taxon": [
          ...             "Saccharina",
          ...             "Saccharina",
          ...             "Saccharina",
          ...             "Agarum",
          ...             "Agarum",
          ...         ],
          ...         "Abundance": [4, 5, 2, 1, 8],
          ...     }
          ... )
          >>> df
             Year       Taxon  Abundance
          0  1999  Saccharina          4
          1  2000  Saccharina          5
          2  2004  Saccharina          2
          3  1999      Agarum          1
          4  2004      Agarum          8
  
          Expose missing pairings of `Year` and `Taxon`:
          >>> df.complete("Year", "Taxon", sort=True)
             Year       Taxon  Abundance
          0  1999      Agarum        1.0
          1  1999  Saccharina        4.0
          2  2000      Agarum        NaN
          3  2000  Saccharina        5.0
          4  2004      Agarum        8.0
          5  2004  Saccharina        2.0
  
          Expose missing years from 1999 to 2004:
          >>> df.complete(
          ...     {"Year": range(df.Year.min(), df.Year.max() + 1)},
          ...     "Taxon",
          ...     sort=True
          ... )
              Year       Taxon  Abundance
          0   1999      Agarum        1.0
          1   1999  Saccharina        4.0
          2   2000      Agarum        NaN
          3   2000  Saccharina        5.0
          4   2001      Agarum        NaN
          5   2001  Saccharina        NaN
          6   2002      Agarum        NaN
          7   2002  Saccharina        NaN
          8   2003      Agarum        NaN
          9   2003  Saccharina        NaN
          10  2004      Agarum        8.0
          11  2004  Saccharina        2.0
  
          Fill missing values:
          >>> df = pd.DataFrame(
          ...     dict(
          ...         group=(1, 2, 1, 2),
          ...         item_id=(1, 2, 2, 3),
          ...         item_name=("a", "a", "b", "b"),
          ...         value1=(1, np.nan, 3, 4),
          ...         value2=range(4, 8),
          ...     )
          ... )
          >>> df
             group  item_id item_name  value1  value2
          0      1        1         a     1.0       4
          1      2        2         a     NaN       5
          2      1        2         b     3.0       6
          3      2        3         b     4.0       7
          >>> df.complete(
          ...     "group",
          ...     ("item_id", "item_name"),
          ...     fill_value={"value1": 0, "value2": 99},
          ...     sort=True
          ... )
             group  item_id item_name  value1  value2
          0      1        1         a     1.0     4.0
          1      1        2         a     0.0    99.0
          2      1        2         b     3.0     6.0
          3      1        3         b     0.0    99.0
          4      2        1         a     0.0    99.0
          5      2        2         a     0.0     5.0
          6      2        2         b     0.0    99.0
          7      2        3         b     4.0     7.0
  
          Limit the fill to only implicit missing values
          by setting explicit to `False`:
          >>> df.complete(
          ...     "group",
          ...     ("item_id", "item_name"),
          ...     fill_value={"value1": 0, "value2": 99},
          ...     explicit=False,
          ...     sort=True
          ... )
             group  item_id item_name  value1  value2
          0      1        1         a     1.0     4.0
          1      1        2         a     0.0    99.0
          2      1        2         b     3.0     6.0
          3      1        3         b     0.0    99.0
          4      2        1         a     0.0    99.0
          5      2        2         a     NaN     5.0
          6      2        2         b     0.0    99.0
          7      2        3         b     4.0     7.0
  
      Args:
          df: A pandas DataFrame.
          *columns: This refers to the columns to be completed.
              It could be column labels (string type),
              a list/tuple of column labels, or a dictionary that pairs
              column labels with new values.
          sort: Sort DataFrame based on *columns.
          by: Label or list of labels to group by.
              The explicit missing rows are returned per group.
          fill_value: Scalar value to use instead of NaN
              for missing combinations. A dictionary, mapping columns names
              to a scalar value is also accepted.
          explicit: Determines if only implicitly missing values
              should be filled (`False`), or all nulls existing in the dataframe
              (`True`). `explicit` is applicable only
              if `fill_value` is not `None`.
  
      Returns:
          A pandas DataFrame with explicit missing rows, if any.
      """  # noqa: E501
  
      if not columns:
          return df
  
      # no copy made of the original dataframe
      # since pd.merge (computed some lines below)
      # makes a new object - essentially a copy
      return _computations_complete(
          df, columns, sort, by, fill_value, explicit
      )
  
file_path: pyjanitor/janitor/functions/complete.py
imports: import functools
  from typing import Any, Dict, List, Optional, Tuple, Union
  import pandas
  import pandas_flavor
  from pandas.api.types import is_list_like, is_scalar
  from pandas.core.common import apply_if_callable
  from janitor.functions.utils import _computations_expand_grid
  from janitor.utils import check, check_column
label_desc: Use image node_id 1 for calling a global function with example usage: complete(df) and returns: _computations_complete, df