diff --git a/docs/source/hypothesis.rst b/docs/source/hypothesis.rst
index e709003..e978d3b 100644
--- a/docs/source/hypothesis.rst
+++ b/docs/source/hypothesis.rst
@@ -27,11 +27,13 @@ can be made about the relationships between ``Column``\s.
 
     schema = DataFrameSchema({
         "height_in_feet": Column(Float, [
-            Hypothesis.two_sample_ttest(groupby="sex",
-                                        groups=["M", "F"],
-                                        relationship="greater_than",
-                                        alpha = 0.05
-                                        ),
+            Hypothesis.two_sample_ttest(
+                groupby="sex",
+                group1="M",
+                group2="F",
+                relationship="greater_than",
+                alpha=0.05,
+                equal_var=True),
         ]),
         "sex": Column(String)
     })
@@ -48,12 +50,12 @@ enables the user to use non-built in functions as follows:
 
     schema = DataFrameSchema({
         "height_in_feet": Column(Float, [
-            Hypothesis(test=stats.ttest_ind,
-                       groupby="sex",
-                       groups=["M", "F"],
-                       relationship="greater_than",
-                       relationship_kwargs={"alpha":0.5}
-                      ),
+            Hypothesis(
+                test=stats.ttest_ind,
+                groupby="sex",
+                groups=["M", "F"],
+                relationship="greater_than",
+                relationship_kwargs={"alpha":0.5, "equal_var": True}),
         ]),
         "sex": Column(String)
     })
diff --git a/pandera/pandera.py b/pandera/pandera.py
index c191f6c..0330ea5 100644
--- a/pandera/pandera.py
+++ b/pandera/pandera.py
@@ -259,6 +259,15 @@ class Hypothesis(Check):
     grouped by another column
     """
 
+    RELATIONSHIPS = {
+        "greater_than": (lambda stat, pvalue, alpha:
+                         stat > 0 and pvalue / 2 < alpha),
+        "less_than": (lambda stat, pvalue, alpha:
+                      stat < 0 and pvalue / 2 < alpha),
+        "not_equal": (lambda stat, pvalue, alpha:
+                      pvalue < alpha),
+    }
+
     def __init__(self, test, relationship, groupby=None, groups=None,
                  test_kwargs=None, relationship_kwargs=None):
         """Initialises hypothesis to perform a hypothesis test on a Column.
@@ -299,11 +308,10 @@ class Hypothesis(Check):
         super(Hypothesis, self).__init__(
             self._check_fn, element_wise=False, groupby=groupby, groups=groups)
 
-    @staticmethod
-    def relationships(relationship):
+    def relationships(self, relationship):
         """Impose a relationship on a supplied Test function.
 
-        :param relationship: Represents what relationship conditions are
+        :param relationship: represents what relationship conditions are
             imposed on the hypothesis test. A function or lambda function can
             be supplied. If a string is provided, a lambda function will be
             returned from Hypothesis.relationships. Available relationships
@@ -312,7 +320,11 @@ class Hypothesis(Check):
 
         """
         if isinstance(relationship, str):
-            try:
+            if relationship not in self.RELATIONSHIPS:
+                raise SchemaError(
+                    "The relationship %s isn't a built in method"
+                    % relationship)
+            else:
                 relationship = {
                     "greater_than": (lambda stat, pvalue, alpha:
                                      stat > 0 and pvalue / 2 < alpha),
@@ -321,11 +333,6 @@ class Hypothesis(Check):
                     "not_equal": (lambda stat, pvalue, alpha:
                                   pvalue < alpha),
                 }[relationship]
-            except SchemaError:
-                raise SchemaError(
-                    "The relationship %s isn't a built in method"
-                    % relationship
-                )
         elif not callable(relationship):
             raise ValueError(
                 "expected relationship to be str or callable, found %s" % type(
@@ -334,7 +341,7 @@ class Hypothesis(Check):
         return relationship
 
     def _check_fn(self, check_obj):
-        """Creates a function fn which is checked via the Check parent class.
+        """Create a function fn which is checked via the Check parent class.
 
         :param dict check_obj: a dictionary of pd.Series to be used by
             `_check_fn` and `_vectorized_series_check`
@@ -345,13 +352,13 @@ class Hypothesis(Check):
             # entire column
             return self.relationship(*self.test(check_obj))
         else:
-            return self.relationship(*self.test(*[check_obj.get(g)
-                                                  for g in self.groups]))
+            return self.relationship(
+                *self.test(*[check_obj.get(g) for g in self.groups]))
 
     @classmethod
-    def two_sample_ttest(cls, groupby, groups, relationship, alpha=None,
-                         relationship_kwargs=None, equal_var=True,
-                         test_kwargs=None):
+    def two_sample_ttest(
+            cls, groupby, group1, group2, relationship,
+            alpha=0.01, equal_var=True, nan_policy="propagate"):
         """Calculate a T-test for the means of two Columns.
 
         This reuses the scipy.stats.ttest_ind to perfom a two-sided test for
@@ -372,70 +379,43 @@ class Hypothesis(Check):
 
             Where specific groups can be obtained from the input dict.
         :type groupby: str|list[str]|callable|None
-        :param groups: The dict input to the `fn` callable will be constrained
-            to the groups specified by `groups`.
-        :type groups: str|list[str]|None
+        :param group1: The first sample group in the `groupby` column.
+        :type group1: str
+        :param group2: The second sample group in the `groupby` column.
+        :type group2: str
         :param relationship: Represents what relationship conditions are
-            imposed on the hypothesis test. A function or lambda function can
-            be supplied. If a string is provided, a lambda function will be
-            returned from Hypothesis.relationships. Available relationships
-            are: "greater_than", "less_than", "not_equal"
-        :type relationship: str|callable
-        :param alpha: (Default value = None) The significance level; the
+            imposed on the hypothesis test. Available relationships
+            are: "greater_than", "less_than", "not_equal". For example,
+            `group1 greater_than group2` specifies an alternative hypothesis
+            that the mean of group1 is greater than group 2 relative to a null
+            hypothesis that they are equal.
+        :type relationship: str
+        :param alpha: (Default value = 0.01) The significance level; the
             probability of rejecting the null hypothesis when it is true. For
-            example, a significance level of 0.05 indicates a 5% risk of
+            example, a significance level of 0.01 indicates a 1% risk of
             concluding that a difference exists when there is no actual
             difference.
-        :param dict relationship_kwargs: (Default value = None) Key Word
-            arguments to be supplied to the relationship function. e.g. `alpha`
-            could be used to specify a threshold in a t-test.
         :param equal_var: (Default value = True) If True (default), perform a
             standard independent 2 sample test that assumes equal population
             variances. If False, perform Welch's t-test, which does not
             assume equal population variance
-        :param dict test_kwargs: (Default value = None) Key Word arguments to
-            be supplied to the test.
-
+        :type equal_var: bool
+        :param nan_policy: Defines how to handle when input returns nan, one of
+            {'propagate', 'raise', 'omit'}, (Default value = 'propagate').
+            For more details see:
+            https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.ttest_ind.html  # noqa E53
+        :type nan_policy: str
         """
-        if len(groups) != 2:
+        if relationship not in cls.RELATIONSHIPS:
             raise SchemaError(
-                "The two sample ttest only works when len(groups)=2, but "
-                "len(%s)= %s" % (groups, len(groups))
-            )
-
-        if relationship_kwargs is None:
-            relationship_kwargs = {}
-        if test_kwargs is None:
-            test_kwargs = {}
-        # handle alpha as an argument on it's own or in relationship_kwargs:
-        if alpha is not None:
-            if "alpha" in relationship_kwargs:
-                raise SchemaError(
-                    "it is ambiguous to specify alpha in the function"
-                    "signature and relationship_kwargs"
-                )
-            relationship_kwargs["alpha"] = alpha
-        else:
-            relationship_kwargs = relationship_kwargs
-
-        # handle equal_var as an argument on it's own or in test_kwargs:
-        if equal_var is not None:
-            if "equal_var" in test_kwargs:
-                raise SchemaError(
-                    "equal_var has been set in both the function signature and"
-                    "test_kwargs, it should be specified only once"
-                )
-            test_kwargs["equal_var"] = equal_var
-        else:
-            test_kwargs = test_kwargs
-
+                "relationship must be one of %s" % set(cls.RELATIONSHIPS))
         return cls(
             test=stats.ttest_ind,
             relationship=relationship,
             groupby=groupby,
-            groups=groups,
-            test_kwargs=test_kwargs,
-            relationship_kwargs=relationship_kwargs
+            groups=[group1, group2],
+            test_kwargs={"equal_var": equal_var, "nan_policy": nan_policy},
+            relationship_kwargs={"alpha": alpha}
         )
 
 

for two sample hypothesis tests, standardize API
For a more intuitive API, two sample `Hypothesis` tests class method definitions should look like this:

```python
def two_sample_hypothesis_test(
    cls, groupby, group1, group2, relationship, alpha=0.01,
    equal_var=True, nan_policy="propagate")
```

which is more intuitive than specifying a list of `groups` that may or may not have 2 elements in it.
diff --git a/tests/test_pandera.py b/tests/test_pandera.py
index 063ac50..8b7d93b 100644
--- a/tests/test_pandera.py
+++ b/tests/test_pandera.py
@@ -569,11 +569,12 @@ def test_hypothesis():
     # Initialise the different ways of calling a test:
     schema_pass_ttest_on_alpha_val_1 = DataFrameSchema({
         "height_in_feet": Column(Float, [
-            Hypothesis.two_sample_ttest(groupby="sex",
-                                        groups=["M", "F"],
-                                        relationship="greater_than",
-                                        alpha=0.5
-                                        ),
+            Hypothesis.two_sample_ttest(
+                groupby="sex",
+                group1="M",
+                group2="F",
+                relationship="greater_than",
+                alpha=0.5),
         ]),
         "sex": Column(String)
     })
@@ -594,10 +595,10 @@ def test_hypothesis():
         "height_in_feet": Column(Float, [
             Hypothesis.two_sample_ttest(
                 groupby="sex",
-                groups=["M", "F"],
+                group1="M",
+                group2="F",
                 relationship="greater_than",
-                relationship_kwargs={"alpha": 0.5}
-            ),
+                alpha=0.5),
         ]),
         "sex": Column(String)
     })
@@ -609,11 +610,12 @@ def test_hypothesis():
 
     schema_fail_ttest_on_alpha_val_1 = DataFrameSchema({
         "height_in_feet": Column(Float, [
-            Hypothesis.two_sample_ttest(groupby="sex",
-                                        groups=["M", "F"],
-                                        relationship="greater_than",
-                                        alpha=0.05
-                                        ),
+            Hypothesis.two_sample_ttest(
+                groupby="sex",
+                group1="M",
+                group2="F",
+                relationship="greater_than",
+                alpha=0.05),
         ]),
         "sex": Column(String)
     })
@@ -624,8 +626,7 @@ def test_hypothesis():
                        groupby="sex",
                        groups=["M", "F"],
                        relationship="greater_than",
-                       relationship_kwargs={"alpha": 0.05}
-                       ),
+                       relationship_kwargs={"alpha": 0.05}),
         ]),
         "sex": Column(String)
     })
@@ -634,10 +635,10 @@ def test_hypothesis():
         "height_in_feet": Column(Float, [
             Hypothesis.two_sample_ttest(
                 groupby="sex",
-                groups=["M", "F"],
+                group1="M",
+                group2="F",
                 relationship="greater_than",
-                relationship_kwargs={"alpha": 0.05}
-            ),
+                alpha=0.05),
         ]),
         "sex": Column(String)
     })
@@ -650,44 +651,32 @@ def test_hypothesis():
         schema_fail_ttest_on_alpha_val_3.validate(df)
 
 
-def test_hypothesis_group_length():
-    # Check that calling two_sample_ttest with len(group)!=2 raises SchemaError
-    with pytest.raises(SchemaError):
-        DataFrameSchema({
-            "height_in_feet": Column(Float, [
-                Hypothesis.two_sample_ttest(groupby="sex",
-                                            groups=["M"],
-                                            relationship="greater_than",
-                                            alpha=0.5
-                                            ),
-            ]),
-            "sex": Column(String)
-        })
-
-    with pytest.raises(SchemaError):
-        DataFrameSchema({
+def test_two_sample_ttest_hypothesis_relationships():
+    """Check allowable relationships in two-sample ttest."""
+    for relationship in Hypothesis.RELATIONSHIPS:
+        schema = DataFrameSchema({
             "height_in_feet": Column(Float, [
-                Hypothesis.two_sample_ttest(groupby="sex",
-                                            groups=["M", "F", "N"],
-                                            relationship="greater_than",
-                                            alpha=0.5
-                                            ),
+                Hypothesis.two_sample_ttest(
+                    groupby="sex",
+                    group1="M",
+                    group2="F",
+                    relationship=relationship,
+                    alpha=0.5),
             ]),
             "sex": Column(String)
         })
+        assert isinstance(schema, DataFrameSchema)
 
-
-def test_hypothesis_unavailable_relationship():
-    # Test that supplying a non-built-in string relationship errors:
-    with pytest.raises(SchemaError):
-        DataFrameSchema({
-            "height_in_feet": Column(Float, [
-                Hypothesis.two_sample_ttest(
+    for relationship in ["foo", "bar", 1, 2, 3, None]:
+        with pytest.raises(SchemaError):
+            DataFrameSchema({
+                "height_in_feet": Column(Float, [
+                    Hypothesis.two_sample_ttest(
                         groupby="sex",
-                        groups=["M"],
-                        relationship="another_relationship",
-                        alpha=0.5
-                        ),
-            ]),
-            "sex": Column(String)
-        })
+                        group1="M",
+                        group2="F",
+                        relationship=relationship,
+                        alpha=0.5),
+                ]),
+                "sex": Column(String)
+            })

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
attrs==22.2.0
Babel==2.11.0
certifi==2021.5.30
charset-normalizer==2.0.12
codecov==2.1.13
coverage==6.2
docutils==0.17.1
enum34==1.1.10
flake8==5.0.4
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==1.1.1
Jinja2==3.0.3
MarkupSafe==2.0.1
mccabe==0.7.0
numpy==1.19.5
packaging==21.3
pandas==1.1.5
-e git+https://github.com/cosmicBboy/pandera.git@be330262bb9ff5cfb4499215e1ae70ead1e9ee52#egg=pandera
pluggy==1.0.0
py==1.11.0
pycodestyle==2.9.1
pyflakes==2.5.0
Pygments==2.14.0
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.27.1
scipy==1.5.4
six==1.17.0
snowballstemmer==2.2.0
Sphinx==4.3.2
sphinx-rtd-theme==1.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==1.2.3
typing_extensions==4.1.1
urllib3==1.26.20
wrapt==1.16.0
zipp==3.6.0

name: pandera
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==22.2.0
      - babel==2.11.0
      - charset-normalizer==2.0.12
      - codecov==2.1.13
      - coverage==6.2
      - docutils==0.17.1
      - enum34==1.1.10
      - flake8==5.0.4
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==1.1.1
      - jinja2==3.0.3
      - markupsafe==2.0.1
      - mccabe==0.7.0
      - numpy==1.19.5
      - packaging==21.3
      - pandas==1.1.5
      - pluggy==1.0.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.27.1
      - scipy==1.5.4
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==4.3.2
      - sphinx-rtd-theme==1.3.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - wrapt==1.16.0
      - zipp==3.6.0
prefix: /opt/conda/envs/pandera

tests/test_pandera.py::test_hypothesis tests/test_pandera.py::test_two_sample_ttest_hypothesis_relationships
tests/test_pandera.py::test_column tests/test_pandera.py::test_series_schema tests/test_pandera.py::test_vectorized_checks tests/test_pandera.py::test_series_schema_multiple_validators tests/test_pandera.py::test_dataframe_schema tests/test_pandera.py::test_dataframe_schema_strict tests/test_pandera.py::test_index_schema tests/test_pandera.py::test_check_function_decorators tests/test_pandera.py::test_check_function_decorator_errors tests/test_pandera.py::test_check_function_decorator_transform tests/test_pandera.py::test_check_input_method_decorators tests/test_pandera.py::test_string_dtypes tests/test_pandera.py::test_nullable_int tests/test_pandera.py::test_coerce_dtype tests/test_pandera.py::test_required tests/test_pandera.py::test_check_groupby tests/test_pandera.py::test_check_groupby_multiple_columns tests/test_pandera.py::test_check_groups tests/test_pandera.py::test_groupby_init_exceptions
docs/source/hypothesis.rst pandera/pandera.py
docs/source/hypothesis.rst pandera/pandera.py