code: def test_nunique(self):
      pdf = pd.DataFrame(
          {"A": [1, 2, 3], "B": [np.nan, 3, np.nan]},
          index=np.random.rand(3),
      )
      psdf = ps.from_pandas(pdf)
  
      # Assert NaNs are dropped by default
      self.assert_eq(psdf.nunique(), pdf.nunique())
  
      # Assert including NaN values
      self.assert_eq(
          psdf.nunique(dropna=False), pdf.nunique(dropna=False)
      )
  
      # Assert approximate counts
      self.assert_eq(
          ps.DataFrame({"A": range(100)}).nunique(approx=True),
          pd.Series([103], index=["A"]),
      )
      self.assert_eq(
          ps.DataFrame({"A": range(100)}).nunique(
              approx=True, rsd=0.01
          ),
          pd.Series([100], index=["A"]),
      )
  
      # Assert unsupported axis value yet
      msg = 'axis should be either 0 or "index" currently.'
      with self.assertRaisesRegex(NotImplementedError, msg):
          psdf.nunique(axis=1)
  
      # multi-index columns
      columns = pd.MultiIndex.from_tuples(
          [("X", "A"), ("Y", "B")], names=["1", "2"]
      )
      pdf.columns = columns
      psdf.columns = columns
  
      self.assert_eq(psdf.nunique(), pdf.nunique())
      self.assert_eq(
          psdf.nunique(dropna=False), pdf.nunique(dropna=False)
      )
  
imports: import unittest
  import numpy
  import pandas
  from pyspark.sql import functions
  from pyspark import pandas
  from pyspark.testing.pandasutils import ComparisonTestBase
  from pyspark.testing.sqlutils import SQLTestUtils
label_desc: Use image node_id 10 for calling the FrameComputeMixin obj's underlying member method code with example usage: obj.test_nunique() without return types