code: def _split_data(self):
      self.loaded = True
  
      if self.connection.execute(
          """
                      SELECT name
                      FROM sqlite_master
                      WHERE type='table'
                        AND name={name}
                  """.format(
              name=self.quote(self.table)
          )
      ).fetchone():
          return
  
      self._data = self.get_data()
  
      if not isinstance(self._data, types.GeneratorType):
          raise TypeError(
              "Iterative pipelines must be passed a generator rather than a dataframe. Did you forget to pass a `chunksize` to lore.io.Connection.dataframe()?"
          )
  
      self.length = 0
  
      # This loop is unfortunately CPU limited rather than IO bound, based on dataframe creation
      # TODO parrallelize with multiple processes?
      for i, dataframe in enumerate(self._data):
          if i == 0:
              self._columns = dataframe.columns
              self.chunksize = len(dataframe)
              buffer = io.StringIO()
              dataframe.info(buf=buffer, memory_usage="deep")
              logger.info(buffer.getvalue())
              logger.info(dataframe.head())
  
              self._datetime_columns = [
                  col
                  for col, type in dataframe.dtypes.iteritems()
                  if type == "datetime64[ns]"
              ]
              with open(self.metadata_path, "wb") as f:
                  pickle.dump(
                      self.datetime_columns, f, pickle.HIGHEST_PROTOCOL
                  )
  
          logger.info("appending %i rows to sqlite" % len(dataframe))
          self.length += len(dataframe)
          dataframe.to_sql(
              self.table,
              self.connection,
              index=False,
              if_exists="append",
          )
  
      if self.subsample:
          with timer("subsample"):
              self.connection.executescript(
                  """
                          BEGIN;
  
                          CREATE TABLE {subsample} AS
                          SELECT * FROM {table}
                          ORDER BY random()
                          LIMIT {limit};
  
                          DROP TABLE {table};
  
                          ALTER TABLE {subsample} RENAME TO {table};
  
                          COMMIT;
                      """.format(
                      table=self.quote(self.table),
                      subsample=self.quote(self.table + "_subsample"),
                      limit=self.subsample,
                  )
              )
          self.length = self.subsample
  
      self._random_split(
          self.table_training, 0, 0.8, stratify=self.stratify
      )
      self._random_split(
          self.table_validation, 0.8, 0.9, stratify=self.stratify
      )
      self._random_split(
          self.table_test, 0.9, 1, stratify=self.stratify
      )
  
      logger.debug(
          "data: %i | training: %i | validation: %i | test: %i"
          % (
              self.length,
              self.table_length(self.table_training),
              self.table_length(self.table_validation),
              self.table_length(self.table_test),
          )
      )
  
imports: from __future__ import absolute_import
  from abc import ABCMeta
  import codecs
  import hashlib
  import io
  import logging
  import os
  import pickle
  import sqlite3
  import types
  import threading
  import lore
  from lore.env import require
  from lore.util import timer, timed
  from lore.pipelines import Observations
  import pandas
label_desc: Use image node_id 20 for calling the Base obj's underlying member method code with example usage: obj._split_data() without return types