docs: def dtypes_summary(df):
      """ Takes in a dataframe and returns a dataframe with
      information on the data-types present in each column.
      Parameters:
      df - DataFrame
          Dataframe to summarize
      """
      output_df = pd.DataFrame([])
      row_count = df.shape[0]
      row_indexes = ['rows_numerical','rows_string','rows_date_time','category_count','largest_category','rows_na','rows_total']
      for colname in df:
          data = df[colname] # data is the pandas series associated with this column
          # number of numerical values in the column
          rows_numerical = pd.to_numeric(data,errors = 'coerce').count()
          # number of values that can't be coerced to a numerical
          rows_string = row_count - rows_numerical
          # number of values that can be coerced to a date-time object
          rows_date_time = pd.to_datetime(data,errors = 'coerce',infer_datetime_format = True).count()
          # categories in column
          value_counts = data.value_counts().reset_index()
          # number of different values in the dataframe
          categories = len(value_counts)
          # largest category
          largest_category = value_counts.iloc[0,1]
          # number of null/missing values
          rows_na = data.isnull().sum()
          # build the output list
          output_data = [rows_numerical, rows_string, rows_date_time, categories, 
                         largest_category,rows_na,row_count]
          # add to dataframe
          output_df.loc[:,colname] = pd.Series(output_data)
  
      # row names
      output_df.index = row_indexes
      return output_df