docs: def dataframe( self, only_successful = True ):
          """Return the results as a pandas DataFrame. Note that there is a danger
          of duplicate labels here, for example if the results contain a value
          with the same name as one of the parameters. To resolve this, parameter names
          take precedence over metadata values, and result names take precedence over
          parameter names.
  
          If the only_successful flag is set (the default), then the DataFrame will
          only include results that completed without an exception; if it is set to
          False, the DataFrame will include all results and also the exception details.
  
          :param only_successful: include only successful experiments (defaults to True)
          :returns: the parameters, results, and metadata in a DataFrame"""
  
          def extract( r ):
              if r[Experiment.METADATA][Experiment.STATUS]:
                  # experiment was a success, include it
                  rd = r[Experiment.METADATA].copy()
                  rd.update(r[Experiment.PARAMETERS])
                  rd.update(r[Experiment.RESULTS])
              else:
                  # experiment returned an exception
                  if not only_successful:
                      # ...but we want it anyway
                      rd = r[Experiment.METADATA].copy()
                      rd.update(r[Experiment.PARAMETERS])
              
                      # ...and there are no results to add
                  else:
                      rd = None
              return rd
  
          records = [ r for r in map(extract, self.results()) if r is not None ]
          return DataFrame.from_records(records)