code: def gather(df, key, values, *args, **kwargs):
      
  
      if len(args) == 0:
          args = df.columns.tolist()
      else:
          args = [a for a in flatten(args)]
  
      if kwargs.get('add_id', False):
          df = df.assign(_ID=np.arange(df.shape[0]))
  
      columns = df.columns.tolist()
      id_vars = [col for col in columns if col not in args]
      return pd.melt(df, id_vars, list(args), key, values)
docs: Melts the specified columns in your DataFrame into two key:value columns.
  
      Args:
          key (str): Name of identifier column.
          values (str): Name of column that will contain values for the key.
          *args (str, int, symbolic): Columns to "melt" into the new key and
              value columns. If no args are specified, all columns are melted
              into they key and value columns.
  
      Kwargs:
          add_id (bool): Boolean value indicating whether to add a `"_ID"`
              column that will preserve information about the original rows
              (useful for being able to re-widen the data later).
  
      Example:
          diamonds >> gather('variable', 'value', ['price', 'depth','x','y','z']) >> head(5)
  
             carat      cut color clarity  table variable  value
          0   0.23    Ideal     E     SI2   55.0    price  326.0
          1   0.21  Premium     E     SI1   61.0    price  326.0
          2   0.23     Good     E     VS1   65.0    price  327.0
          3   0.29  Premium     I     VS2   58.0    price  334.0
          4   0.31     Good     J     SI2   58.0    price  335.0