We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[FEAT] Mixed Nulls - catch mixed nulls on non string columns (np.NaN/pd.NaN/Null/None/etc.)
**Docs**

API Reference should include what are the DEFAULT NULLS that are checks (currently this can be found only by going into source)
Example notebook can also print out these nulls for convenience.

**Null Types**
1. NaT nulls not caught @chelseatroy can you elaborate?
3. Seems that list currently includes only strings (and null character). Does this catch also null objects? (e.g. the python None. Numpy and pandas nulls. or any other null that is likely to find it's way due to multiple feature engineering backends)



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `deepchecks/tabular/checks/integrity/mixed_nulls.py`
Content:
```
1 # ----------------------------------------------------------------------------
2 # Copyright (C) 2021-2022 Deepchecks (https://www.deepchecks.com)
3 #
4 # This file is part of Deepchecks.
5 # Deepchecks is distributed under the terms of the GNU Affero General
6 # Public License (version 3 or later).
7 # You should have received a copy of the GNU Affero General Public License
8 # along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.
9 # ----------------------------------------------------------------------------
10 #
11 """Module contains Mixed Nulls check."""
12 from collections import defaultdict
13 from typing import Union, Dict, List, Iterable
14 
15 import numpy as np
16 import pandas as pd
17 
18 from deepchecks.tabular import Context, SingleDatasetCheck
19 from deepchecks.core import CheckResult, ConditionResult, ConditionCategory
20 from deepchecks.core.errors import DeepchecksValueError
21 from deepchecks.utils.dataframes import select_from_dataframe
22 from deepchecks.utils.features import N_TOP_MESSAGE, column_importance_sorter_df
23 from deepchecks.utils.strings import string_baseform, format_percent
24 from deepchecks.utils.typing import Hashable
25 
26 
27 __all__ = ['MixedNulls']
28 
29 
30 DEFAULT_NULL_VALUES = {'none', 'null', 'nan', 'na', '', '\x00', '\x00\x00'}
31 
32 
33 class MixedNulls(SingleDatasetCheck):
34     """Search for various types of null values in a string column(s), including string representations of null.
35 
36     Parameters
37     ----------
38     null_string_list : Iterable[str] , default: None
39         List of strings to be considered alternative null representations
40     check_nan : bool , default: True
41         Whether to add to null list to check also NaN values
42     columns : Union[Hashable, List[Hashable]] , default: None
43         Columns to check, if none are given checks all columns except ignored ones.
44     ignore_columns : Union[Hashable, List[Hashable]] , default: None
45         Columns to ignore, if none given checks based on columns variable
46     n_top_columns : int , optional
47         amount of columns to show ordered by feature importance (date, index, label are first)
48     """
49 
50     def __init__(
51         self,
52         null_string_list: Iterable[str] = None,
53         check_nan: bool = True,
54         columns: Union[Hashable, List[Hashable], None] = None,
55         ignore_columns: Union[Hashable, List[Hashable], None] = None,
56         n_top_columns: int = 10,
57         **kwargs
58     ):
59         super().__init__(**kwargs)
60         self.null_string_list = null_string_list
61         self.check_nan = check_nan
62         self.columns = columns
63         self.ignore_columns = ignore_columns
64         self.n_top_columns = n_top_columns
65 
66     def run_logic(self, context: Context, dataset_type: str = 'train') -> CheckResult:
67         """Run check.
68 
69         Returns
70         -------
71         CheckResult
72             DataFrame with columns ('Column Name', 'Value', 'Count', 'Percentage') for any column which
73             have more than 1 null values.
74         """
75         if dataset_type == 'train':
76             dataset = context.train
77         else:
78             dataset = context.test
79         df = dataset.data
80 
81         df = select_from_dataframe(df, self.columns, self.ignore_columns)
82         null_string_list: set = self._validate_null_string_list(self.null_string_list, self.check_nan)
83 
84         # Result value
85         display_array = []
86         result_dict = defaultdict(dict)
87 
88         for column_name in list(df.columns):
89             column_data = df[column_name]
90             # TODO: Modify this once Dataset type casting mechanism is done
91             if column_data.dtype != pd.StringDtype:
92                 continue
93             # Get counts of all values in series including NaNs, in sorted order of count
94             column_counts: pd.Series = column_data.value_counts(dropna=False)
95             # Filter out values not in the nulls list
96             null_counts = {value: count for value, count in column_counts.items()
97                            if string_baseform(value) in null_string_list}
98             if len(null_counts) < 2:
99                 continue
100             # Save the column info
101             for null_value, count in null_counts.items():
102                 percent = count / len(column_data)
103                 display_array.append([column_name, null_value, count, format_percent(percent)])
104                 result_dict[column_name][null_value] = {'count': count, 'percent': percent}
105 
106         # Create dataframe to display table
107         if display_array:
108             df_graph = pd.DataFrame(display_array, columns=['Column Name', 'Value', 'Count', 'Percent of data'])
109             df_graph = df_graph.set_index(['Column Name', 'Value'])
110             df_graph = column_importance_sorter_df(df_graph, dataset, context.features_importance,
111                                                    self.n_top_columns, col='Column Name')
112             display = [N_TOP_MESSAGE % self.n_top_columns, df_graph]
113         else:
114             display = None
115 
116         return CheckResult(result_dict, display=display)
117 
118     def _validate_null_string_list(self, nsl, check_nan: bool) -> set:
119         """Validate the object given is a list of strings. If null is given return default list of null values.
120 
121         Parameters
122         ----------
123         nsl
124             Object to validate
125         check_nan : bool
126             Whether to add to null list to check also NaN values
127         Returns
128         -------
129         set
130             Returns list of null values as set object
131         """
132         result: set
133         if nsl:
134             if not isinstance(nsl, Iterable):
135                 raise DeepchecksValueError('null_string_list must be an iterable')
136             if len(nsl) == 0:
137                 raise DeepchecksValueError("null_string_list can't be empty list")
138             if any((not isinstance(string, str) for string in nsl)):
139                 raise DeepchecksValueError("null_string_list must contain only items of type 'str'")
140             result = set(nsl)
141         else:
142             # Default values
143             result = set(DEFAULT_NULL_VALUES)
144         if check_nan is None or check_nan is True:
145             result.add(np.NaN)
146 
147         return result
148 
149     def add_condition_different_nulls_not_more_than(self, max_allowed_null_types: int = 1):
150         """Add condition - require column not to have more than given number of different null values.
151 
152         Parameters
153         ----------
154         max_allowed_null_types : int , default: 1
155             Number of different null value types which is the maximum allowed.
156         """
157         def condition(result: Dict) -> ConditionResult:
158             not_passing_columns = {}
159             for column in result.keys():
160                 nulls = result[column]
161                 num_nulls = len(nulls)
162                 if num_nulls > max_allowed_null_types:
163                     not_passing_columns[column] = num_nulls
164             if not_passing_columns:
165                 return ConditionResult(ConditionCategory.FAIL,
166                                        'Found columns with amount of null types above threshold: '
167                                        f'{not_passing_columns}')
168             else:
169                 return ConditionResult(ConditionCategory.PASS)
170 
171         return self.add_condition(f'Not more than {max_allowed_null_types} different null types',
172                                   condition)
173
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/deepchecks/tabular/checks/integrity/mixed_nulls.py b/deepchecks/tabular/checks/integrity/mixed_nulls.py
--- a/deepchecks/tabular/checks/integrity/mixed_nulls.py
+++ b/deepchecks/tabular/checks/integrity/mixed_nulls.py
@@ -9,10 +9,9 @@
 # ----------------------------------------------------------------------------
 #
 """Module contains Mixed Nulls check."""
-from collections import defaultdict
+from collections import defaultdict, Counter
 from typing import Union, Dict, List, Iterable
 
-import numpy as np
 import pandas as pd
 
 from deepchecks.tabular import Context, SingleDatasetCheck
@@ -22,6 +21,7 @@
 from deepchecks.utils.features import N_TOP_MESSAGE, column_importance_sorter_df
 from deepchecks.utils.strings import string_baseform, format_percent
 from deepchecks.utils.typing import Hashable
+from pkg_resources import parse_version
 
 
 __all__ = ['MixedNulls']
@@ -31,7 +31,7 @@
 
 
 class MixedNulls(SingleDatasetCheck):
-    """Search for various types of null values in a string column(s), including string representations of null.
+    """Search for various types of null values, including string representations of null.
 
     Parameters
     ----------
@@ -79,7 +79,7 @@
         df = dataset.data
 
         df = select_from_dataframe(df, self.columns, self.ignore_columns)
-        null_string_list: set = self._validate_null_string_list(self.null_string_list, self.check_nan)
+        null_string_list: set = self._validate_null_string_list(self.null_string_list)
 
         # Result value
         display_array = []
@@ -87,14 +87,17 @@
 
         for column_name in list(df.columns):
             column_data = df[column_name]
-            # TODO: Modify this once Dataset type casting mechanism is done
-            if column_data.dtype != pd.StringDtype:
-                continue
-            # Get counts of all values in series including NaNs, in sorted order of count
-            column_counts: pd.Series = column_data.value_counts(dropna=False)
+            # Pandas version 1.3.X and lower doesn't support counting separate NaN values in value_counts
+            if parse_version(pd.__version__) < parse_version('1.4.0'):
+                column_counts = Counter(column_data)
+            else:
+                # Get counts of all values in series including NaNs
+                column_counts: pd.Series = column_data.value_counts(dropna=False)
+
             # Filter out values not in the nulls list
             null_counts = {value: count for value, count in column_counts.items()
-                           if string_baseform(value) in null_string_list}
+                           if (self.check_nan and pd.isnull(value)) or (string_baseform(value) in null_string_list)}
+
             if len(null_counts) < 2:
                 continue
             # Save the column info
@@ -115,15 +118,14 @@
 
         return CheckResult(result_dict, display=display)
 
-    def _validate_null_string_list(self, nsl, check_nan: bool) -> set:
+    def _validate_null_string_list(self, nsl) -> set:
         """Validate the object given is a list of strings. If null is given return default list of null values.
 
         Parameters
         ----------
         nsl
             Object to validate
-        check_nan : bool
-            Whether to add to null list to check also NaN values
+
         Returns
         -------
         set
@@ -141,8 +143,6 @@
         else:
             # Default values
             result = set(DEFAULT_NULL_VALUES)
-        if check_nan is None or check_nan is True:
-            result.add(np.NaN)
 
         return result

{"golden_diff": "diff --git a/deepchecks/tabular/checks/integrity/mixed_nulls.py b/deepchecks/tabular/checks/integrity/mixed_nulls.py\n--- a/deepchecks/tabular/checks/integrity/mixed_nulls.py\n+++ b/deepchecks/tabular/checks/integrity/mixed_nulls.py\n@@ -9,10 +9,9 @@\n # ----------------------------------------------------------------------------\n #\n \"\"\"Module contains Mixed Nulls check.\"\"\"\n-from collections import defaultdict\n+from collections import defaultdict, Counter\n from typing import Union, Dict, List, Iterable\n \n-import numpy as np\n import pandas as pd\n \n from deepchecks.tabular import Context, SingleDatasetCheck\n@@ -22,6 +21,7 @@\n from deepchecks.utils.features import N_TOP_MESSAGE, column_importance_sorter_df\n from deepchecks.utils.strings import string_baseform, format_percent\n from deepchecks.utils.typing import Hashable\n+from pkg_resources import parse_version\n \n \n __all__ = ['MixedNulls']\n@@ -31,7 +31,7 @@\n \n \n class MixedNulls(SingleDatasetCheck):\n-    \"\"\"Search for various types of null values in a string column(s), including string representations of null.\n+    \"\"\"Search for various types of null values, including string representations of null.\n \n     Parameters\n     ----------\n@@ -79,7 +79,7 @@\n         df = dataset.data\n \n         df = select_from_dataframe(df, self.columns, self.ignore_columns)\n-        null_string_list: set = self._validate_null_string_list(self.null_string_list, self.check_nan)\n+        null_string_list: set = self._validate_null_string_list(self.null_string_list)\n \n         # Result value\n         display_array = []\n@@ -87,14 +87,17 @@\n \n         for column_name in list(df.columns):\n             column_data = df[column_name]\n-            # TODO: Modify this once Dataset type casting mechanism is done\n-            if column_data.dtype != pd.StringDtype:\n-                continue\n-            # Get counts of all values in series including NaNs, in sorted order of count\n-            column_counts: pd.Series = column_data.value_counts(dropna=False)\n+            # Pandas version 1.3.X and lower doesn't support counting separate NaN values in value_counts\n+            if parse_version(pd.__version__) < parse_version('1.4.0'):\n+                column_counts = Counter(column_data)\n+            else:\n+                # Get counts of all values in series including NaNs\n+                column_counts: pd.Series = column_data.value_counts(dropna=False)\n+\n             # Filter out values not in the nulls list\n             null_counts = {value: count for value, count in column_counts.items()\n-                           if string_baseform(value) in null_string_list}\n+                           if (self.check_nan and pd.isnull(value)) or (string_baseform(value) in null_string_list)}\n+\n             if len(null_counts) < 2:\n                 continue\n             # Save the column info\n@@ -115,15 +118,14 @@\n \n         return CheckResult(result_dict, display=display)\n \n-    def _validate_null_string_list(self, nsl, check_nan: bool) -> set:\n+    def _validate_null_string_list(self, nsl) -> set:\n         \"\"\"Validate the object given is a list of strings. If null is given return default list of null values.\n \n         Parameters\n         ----------\n         nsl\n             Object to validate\n-        check_nan : bool\n-            Whether to add to null list to check also NaN values\n+\n         Returns\n         -------\n         set\n@@ -141,8 +143,6 @@\n         else:\n             # Default values\n             result = set(DEFAULT_NULL_VALUES)\n-        if check_nan is None or check_nan is True:\n-            result.add(np.NaN)\n \n         return result\n", "issue": "[FEAT] Mixed Nulls - catch mixed nulls on non string columns (np.NaN/pd.NaN/Null/None/etc.)\n**Docs**\r\n\r\nAPI Reference should include what are the DEFAULT NULLS that are checks (currently this can be found only by going into source)\r\nExample notebook can also print out these nulls for convenience.\r\n\r\n**Null Types**\r\n1. NaT nulls not caught @chelseatroy can you elaborate?\r\n3. Seems that list currently includes only strings (and null character). Does this catch also null objects? (e.g. the python None. Numpy and pandas nulls. or any other null that is likely to find it's way due to multiple feature engineering backends)\r\n\r\n\n", "before_files": [{"content": "# ----------------------------------------------------------------------------\n# Copyright (C) 2021-2022 Deepchecks (https://www.deepchecks.com)\n#\n# This file is part of Deepchecks.\n# Deepchecks is distributed under the terms of the GNU Affero General\n# Public License (version 3 or later).\n# You should have received a copy of the GNU Affero General Public License\n# along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.\n# ----------------------------------------------------------------------------\n#\n\"\"\"Module contains Mixed Nulls check.\"\"\"\nfrom collections import defaultdict\nfrom typing import Union, Dict, List, Iterable\n\nimport numpy as np\nimport pandas as pd\n\nfrom deepchecks.tabular import Context, SingleDatasetCheck\nfrom deepchecks.core import CheckResult, ConditionResult, ConditionCategory\nfrom deepchecks.core.errors import DeepchecksValueError\nfrom deepchecks.utils.dataframes import select_from_dataframe\nfrom deepchecks.utils.features import N_TOP_MESSAGE, column_importance_sorter_df\nfrom deepchecks.utils.strings import string_baseform, format_percent\nfrom deepchecks.utils.typing import Hashable\n\n\n__all__ = ['MixedNulls']\n\n\nDEFAULT_NULL_VALUES = {'none', 'null', 'nan', 'na', '', '\\x00', '\\x00\\x00'}\n\n\nclass MixedNulls(SingleDatasetCheck):\n    \"\"\"Search for various types of null values in a string column(s), including string representations of null.\n\n    Parameters\n    ----------\n    null_string_list : Iterable[str] , default: None\n        List of strings to be considered alternative null representations\n    check_nan : bool , default: True\n        Whether to add to null list to check also NaN values\n    columns : Union[Hashable, List[Hashable]] , default: None\n        Columns to check, if none are given checks all columns except ignored ones.\n    ignore_columns : Union[Hashable, List[Hashable]] , default: None\n        Columns to ignore, if none given checks based on columns variable\n    n_top_columns : int , optional\n        amount of columns to show ordered by feature importance (date, index, label are first)\n    \"\"\"\n\n    def __init__(\n        self,\n        null_string_list: Iterable[str] = None,\n        check_nan: bool = True,\n        columns: Union[Hashable, List[Hashable], None] = None,\n        ignore_columns: Union[Hashable, List[Hashable], None] = None,\n        n_top_columns: int = 10,\n        **kwargs\n    ):\n        super().__init__(**kwargs)\n        self.null_string_list = null_string_list\n        self.check_nan = check_nan\n        self.columns = columns\n        self.ignore_columns = ignore_columns\n        self.n_top_columns = n_top_columns\n\n    def run_logic(self, context: Context, dataset_type: str = 'train') -> CheckResult:\n        \"\"\"Run check.\n\n        Returns\n        -------\n        CheckResult\n            DataFrame with columns ('Column Name', 'Value', 'Count', 'Percentage') for any column which\n            have more than 1 null values.\n        \"\"\"\n        if dataset_type == 'train':\n            dataset = context.train\n        else:\n            dataset = context.test\n        df = dataset.data\n\n        df = select_from_dataframe(df, self.columns, self.ignore_columns)\n        null_string_list: set = self._validate_null_string_list(self.null_string_list, self.check_nan)\n\n        # Result value\n        display_array = []\n        result_dict = defaultdict(dict)\n\n        for column_name in list(df.columns):\n            column_data = df[column_name]\n            # TODO: Modify this once Dataset type casting mechanism is done\n            if column_data.dtype != pd.StringDtype:\n                continue\n            # Get counts of all values in series including NaNs, in sorted order of count\n            column_counts: pd.Series = column_data.value_counts(dropna=False)\n            # Filter out values not in the nulls list\n            null_counts = {value: count for value, count in column_counts.items()\n                           if string_baseform(value) in null_string_list}\n            if len(null_counts) < 2:\n                continue\n            # Save the column info\n            for null_value, count in null_counts.items():\n                percent = count / len(column_data)\n                display_array.append([column_name, null_value, count, format_percent(percent)])\n                result_dict[column_name][null_value] = {'count': count, 'percent': percent}\n\n        # Create dataframe to display table\n        if display_array:\n            df_graph = pd.DataFrame(display_array, columns=['Column Name', 'Value', 'Count', 'Percent of data'])\n            df_graph = df_graph.set_index(['Column Name', 'Value'])\n            df_graph = column_importance_sorter_df(df_graph, dataset, context.features_importance,\n                                                   self.n_top_columns, col='Column Name')\n            display = [N_TOP_MESSAGE % self.n_top_columns, df_graph]\n        else:\n            display = None\n\n        return CheckResult(result_dict, display=display)\n\n    def _validate_null_string_list(self, nsl, check_nan: bool) -> set:\n        \"\"\"Validate the object given is a list of strings. If null is given return default list of null values.\n\n        Parameters\n        ----------\n        nsl\n            Object to validate\n        check_nan : bool\n            Whether to add to null list to check also NaN values\n        Returns\n        -------\n        set\n            Returns list of null values as set object\n        \"\"\"\n        result: set\n        if nsl:\n            if not isinstance(nsl, Iterable):\n                raise DeepchecksValueError('null_string_list must be an iterable')\n            if len(nsl) == 0:\n                raise DeepchecksValueError(\"null_string_list can't be empty list\")\n            if any((not isinstance(string, str) for string in nsl)):\n                raise DeepchecksValueError(\"null_string_list must contain only items of type 'str'\")\n            result = set(nsl)\n        else:\n            # Default values\n            result = set(DEFAULT_NULL_VALUES)\n        if check_nan is None or check_nan is True:\n            result.add(np.NaN)\n\n        return result\n\n    def add_condition_different_nulls_not_more_than(self, max_allowed_null_types: int = 1):\n        \"\"\"Add condition - require column not to have more than given number of different null values.\n\n        Parameters\n        ----------\n        max_allowed_null_types : int , default: 1\n            Number of different null value types which is the maximum allowed.\n        \"\"\"\n        def condition(result: Dict) -> ConditionResult:\n            not_passing_columns = {}\n            for column in result.keys():\n                nulls = result[column]\n                num_nulls = len(nulls)\n                if num_nulls > max_allowed_null_types:\n                    not_passing_columns[column] = num_nulls\n            if not_passing_columns:\n                return ConditionResult(ConditionCategory.FAIL,\n                                       'Found columns with amount of null types above threshold: '\n                                       f'{not_passing_columns}')\n            else:\n                return ConditionResult(ConditionCategory.PASS)\n\n        return self.add_condition(f'Not more than {max_allowed_null_types} different null types',\n                                  condition)\n", "path": "deepchecks/tabular/checks/integrity/mixed_nulls.py"}], "after_files": [{"content": "# ----------------------------------------------------------------------------\n# Copyright (C) 2021-2022 Deepchecks (https://www.deepchecks.com)\n#\n# This file is part of Deepchecks.\n# Deepchecks is distributed under the terms of the GNU Affero General\n# Public License (version 3 or later).\n# You should have received a copy of the GNU Affero General Public License\n# along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.\n# ----------------------------------------------------------------------------\n#\n\"\"\"Module contains Mixed Nulls check.\"\"\"\nfrom collections import defaultdict, Counter\nfrom typing import Union, Dict, List, Iterable\n\nimport pandas as pd\n\nfrom deepchecks.tabular import Context, SingleDatasetCheck\nfrom deepchecks.core import CheckResult, ConditionResult, ConditionCategory\nfrom deepchecks.core.errors import DeepchecksValueError\nfrom deepchecks.utils.dataframes import select_from_dataframe\nfrom deepchecks.utils.features import N_TOP_MESSAGE, column_importance_sorter_df\nfrom deepchecks.utils.strings import string_baseform, format_percent\nfrom deepchecks.utils.typing import Hashable\nfrom pkg_resources import parse_version\n\n\n__all__ = ['MixedNulls']\n\n\nDEFAULT_NULL_VALUES = {'none', 'null', 'nan', 'na', '', '\\x00', '\\x00\\x00'}\n\n\nclass MixedNulls(SingleDatasetCheck):\n    \"\"\"Search for various types of null values, including string representations of null.\n\n    Parameters\n    ----------\n    null_string_list : Iterable[str] , default: None\n        List of strings to be considered alternative null representations\n    check_nan : bool , default: True\n        Whether to add to null list to check also NaN values\n    columns : Union[Hashable, List[Hashable]] , default: None\n        Columns to check, if none are given checks all columns except ignored ones.\n    ignore_columns : Union[Hashable, List[Hashable]] , default: None\n        Columns to ignore, if none given checks based on columns variable\n    n_top_columns : int , optional\n        amount of columns to show ordered by feature importance (date, index, label are first)\n    \"\"\"\n\n    def __init__(\n        self,\n        null_string_list: Iterable[str] = None,\n        check_nan: bool = True,\n        columns: Union[Hashable, List[Hashable], None] = None,\n        ignore_columns: Union[Hashable, List[Hashable], None] = None,\n        n_top_columns: int = 10,\n        **kwargs\n    ):\n        super().__init__(**kwargs)\n        self.null_string_list = null_string_list\n        self.check_nan = check_nan\n        self.columns = columns\n        self.ignore_columns = ignore_columns\n        self.n_top_columns = n_top_columns\n\n    def run_logic(self, context: Context, dataset_type: str = 'train') -> CheckResult:\n        \"\"\"Run check.\n\n        Returns\n        -------\n        CheckResult\n            DataFrame with columns ('Column Name', 'Value', 'Count', 'Percentage') for any column which\n            have more than 1 null values.\n        \"\"\"\n        if dataset_type == 'train':\n            dataset = context.train\n        else:\n            dataset = context.test\n        df = dataset.data\n\n        df = select_from_dataframe(df, self.columns, self.ignore_columns)\n        null_string_list: set = self._validate_null_string_list(self.null_string_list)\n\n        # Result value\n        display_array = []\n        result_dict = defaultdict(dict)\n\n        for column_name in list(df.columns):\n            column_data = df[column_name]\n            # Pandas version 1.3.X and lower doesn't support counting separate NaN values in value_counts\n            if parse_version(pd.__version__) < parse_version('1.4.0'):\n                column_counts = Counter(column_data)\n            else:\n                # Get counts of all values in series including NaNs\n                column_counts: pd.Series = column_data.value_counts(dropna=False)\n\n            # Filter out values not in the nulls list\n            null_counts = {value: count for value, count in column_counts.items()\n                           if (self.check_nan and pd.isnull(value)) or (string_baseform(value) in null_string_list)}\n\n            if len(null_counts) < 2:\n                continue\n            # Save the column info\n            for null_value, count in null_counts.items():\n                percent = count / len(column_data)\n                display_array.append([column_name, null_value, count, format_percent(percent)])\n                result_dict[column_name][null_value] = {'count': count, 'percent': percent}\n\n        # Create dataframe to display table\n        if display_array:\n            df_graph = pd.DataFrame(display_array, columns=['Column Name', 'Value', 'Count', 'Percent of data'])\n            df_graph = df_graph.set_index(['Column Name', 'Value'])\n            df_graph = column_importance_sorter_df(df_graph, dataset, context.features_importance,\n                                                   self.n_top_columns, col='Column Name')\n            display = [N_TOP_MESSAGE % self.n_top_columns, df_graph]\n        else:\n            display = None\n\n        return CheckResult(result_dict, display=display)\n\n    def _validate_null_string_list(self, nsl) -> set:\n        \"\"\"Validate the object given is a list of strings. If null is given return default list of null values.\n\n        Parameters\n        ----------\n        nsl\n            Object to validate\n\n        Returns\n        -------\n        set\n            Returns list of null values as set object\n        \"\"\"\n        result: set\n        if nsl:\n            if not isinstance(nsl, Iterable):\n                raise DeepchecksValueError('null_string_list must be an iterable')\n            if len(nsl) == 0:\n                raise DeepchecksValueError(\"null_string_list can't be empty list\")\n            if any((not isinstance(string, str) for string in nsl)):\n                raise DeepchecksValueError(\"null_string_list must contain only items of type 'str'\")\n            result = set(nsl)\n        else:\n            # Default values\n            result = set(DEFAULT_NULL_VALUES)\n\n        return result\n\n    def add_condition_different_nulls_not_more_than(self, max_allowed_null_types: int = 1):\n        \"\"\"Add condition - require column not to have more than given number of different null values.\n\n        Parameters\n        ----------\n        max_allowed_null_types : int , default: 1\n            Number of different null value types which is the maximum allowed.\n        \"\"\"\n        def condition(result: Dict) -> ConditionResult:\n            not_passing_columns = {}\n            for column in result.keys():\n                nulls = result[column]\n                num_nulls = len(nulls)\n                if num_nulls > max_allowed_null_types:\n                    not_passing_columns[column] = num_nulls\n            if not_passing_columns:\n                return ConditionResult(ConditionCategory.FAIL,\n                                       'Found columns with amount of null types above threshold: '\n                                       f'{not_passing_columns}')\n            else:\n                return ConditionResult(ConditionCategory.PASS)\n\n        return self.add_condition(f'Not more than {max_allowed_null_types} different null types',\n                                  condition)\n", "path": "deepchecks/tabular/checks/integrity/mixed_nulls.py"}]}