code: from typing import List, Tuple
  
  import pandas as pd
  
  
  @pd.api.extensions.register_dataframe_accessor("tag")
  class CaTaggingAccessor:
      def __init__(self, df: pd.DataFrame):
          self._df = df
  
      def group_by_sentences(self):
          yield from (x[1] for x in self._df.groupby("sentence_id"))
  
      def group_by_documents(self):
          yield from (x[1] for x in self._df.groupby("document_id"))
  
      def number_of_sentences(self):
          return len(self._df.groupby("sentence_id"))
  
      def number_of_documents(self):
          return len(self._df.groupby("document_id"))
  
      def split_x_y_sentencewise(self) -> Tuple[List[List[str]], List[List[str]]]:
          X = []
          y = []
  
          for sent in self._df.tag.group_by_sentences():
              words = list(sent["word"])
              labels = list(sent["label"])
  
              X.append(words)
              y.append(labels)
  
          return X, y
  
      def get_times_per_document(self) -> List[int]:
          t = []
  
          # Right now, we assume that the time per token is the same
          # for a sentence. This might be an invalid assumption
          for df in self._df.tag.group_by_sentences():
              t.append(df["t"].values[0])
  
          return t
  
      def group_by_documents_x_y(self) -> Tuple[List[List[List[str]]], List[List[List[str]]]]:
          """Returns a list of documents that each contain a list of sentences and
          their respective labels grouped the same way.
          """
          X = []
          y = []
  
          for doc in self._df.tag.group_by_documents():
              X_doc = []
              y_doc = []
              for sent in doc.tag.group_by_sentences():
                  words = list(sent["word"])
                  labels = list(sent["label"])
  
                  X_doc.append(words)
                  y_doc.append(labels)
  
              X.append(X_doc)
              y.append(y_doc)
  
          return X, y
  
      def group_by_sentences_x_y(self) -> Tuple[List[List[str]], List[List[str]]]:
          """Returns a list of sentences and their respective labels grouped the same way."""
          X = []
          y = []
  
          for sent in self._df.tag.group_by_sentences():
              words = list(sent["word"])
              labels = list(sent["label"])
  
              assert len(words) == len(labels)
  
              X.append(words)
              y.append(labels)
  
          return X, y
  
  
  @pd.api.extensions.register_dataframe_accessor("dclass")
  class CaDocumentClassificationAccessor:
      def __init__(self, df: pd.DataFrame):
          self._df = df
  
      def split_x_y(self) -> Tuple[List[str], List[str]]:
          X = self._df["sentence"]
          y = self._df["label"]
          return X.values.tolist(), y.values.tolist()
  
      def get_time_per_sentence(self) -> List[int]:
          return self._df["t"].values.tolist()
  
  
  @pd.api.extensions.register_dataframe_accessor("pair")
  class CaPairAccessor:
      def __init__(self, df: pd.DataFrame):
          self._df = df
  
      def split_args_y(self) -> Tuple[List[str], List[str], List[str]]:
          args1 = self._df["arg1"].values.tolist()
          args2 = self._df["arg2"].values.tolist()
          label = self._df["label"].values.tolist()
          return args1, args2, label
  
      def get_time_per_sentence(self) -> List[int]:
          return self._df["t"].values.tolist()
  
apis: pandas.api.extensions.register_dataframe_accessor