docs: def to_df(self, variables=None, format='wide', fillna=np.nan, **kwargs):
          ''' Merge variables into a single pandas DataFrame.
  
          Args:
              variables (list): Optional list of column names to retain; if None,
                  all variables are returned.
              format (str): Whether to return a DataFrame in 'wide' or 'long'
                  format. In 'wide' format, each row is defined by a unique
                  onset/duration, and each variable is in a separate column. In
                  'long' format, each row is a unique combination of onset,
                  duration, and variable name, and a single 'amplitude' column
                  provides the value.
              fillna: Replace missing values with the specified value.
              kwargs: Optional keyword arguments to pass onto each Variable's
                  to_df() call (e.g., condition, entities, and timing).
  
          Returns: A pandas DataFrame.
          '''
  
          if variables is None:
              variables = list(self.variables.keys())
  
          # Can receive already-selected Variables from sub-classes
          if not isinstance(variables[0], BIDSVariable):
              variables = [v for v in self.variables.values()
                           if v.name in variables]
  
          dfs = [v.to_df(**kwargs) for v in variables]
          df = pd.concat(dfs, axis=0, sort=True)
  
          if format == 'long':
              return df.reset_index(drop=True).fillna(fillna)
  
          ind_cols = list(set(df.columns) - {'condition', 'amplitude'})
  
          df['amplitude'] = df['amplitude'].fillna('n/a')
          df = df.pivot_table(index=ind_cols, columns='condition',
                              values='amplitude', aggfunc='first')
          df = df.reset_index().replace('n/a', fillna)
          df.columns.name = None
          return df