code: def compute_panel(cls, data, scales, **params):
          
          if not len(data):
              return type(data)()
  
          stats = []
          for _, old in data.groupby('group'):
              new = cls.compute_group(old, scales, **params)
              unique = uniquecols(old)
              missing = unique.columns.difference(new.columns)
              u = unique.loc[[0]*len(new), missing].reset_index(drop=True)
              # concat can have problems with empty dataframes that
              # have an index
              if u.empty and len(u):
                  u = type(data)()
  
              df = pd.concat([new, u], axis=1)
              stats.append(df)
  
          stats = pd.concat(stats, axis=0, ignore_index=True)
  
          # Note: If the data coming in has columns with non-unique
          # values with-in group(s), this implementation loses the
          # columns. Individual stats may want to do some preparation
          # before then fall back on this implementation or override
          # it completely.
          return stats
docs: Calculate the stats of all the groups and
          return the results in a single dataframe.
  
          This is a default function that can be overriden
          by individual stats
  
          Parameters
          ----------
          data : dataframe
              data for the computing
          scales : types.SimpleNamespace
              x (``scales.x``) and y (``scales.y``) scale objects.
              The most likely reason to use scale information is
              to find out the physical size of a scale. e.g::
  
                  range_x = scales.x.dimension()
  
          params : dict
              The parameters for the stat. It includes default
              values if user did not set a particular parameter.