<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def unstack(self, column_names, new_column_name=None):
 """ Concatenate values from one or two columns into one column, grouping by all other columns. The resulting column could be of type list, array or dictionary. If ``column_names`` is a numeric column, the result will be of array.array type. If ``column_names`` is a non-numeric column, the new column will be of list type. If ``column_names`` is a list of two columns, the new column will be of dict type where the keys are taken from the first column in the list. Parameters column_names : str | [str, str] The column(s) that is(are) to be concatenated. If str, then collapsed column type is either array or list. If [str, str], then collapsed column type is dict new_column_name : str, optional New column name. If not given, a name is generated automatically. Returns ------- out : SFrame A new SFrame containing the grouped columns as well as the new column. See Also -------- stack : The inverse of unstack. groupby : ``unstack`` is a special version of ``groupby`` that uses the :mod:`~turicreate.aggregate.CONCAT` aggregator Notes ----- - There is no guarantee the resulting SFrame maintains the same order as the original SFrame. - Missing values are maintained during unstack. - When unstacking into a dictionary, if there is more than one instance of a given key for a particular group, an arbitrary value is selected. Examples -------- | topic | words | | elephant | {'a': 1, 'b': 2} | | dog | {'c': 1} | | cat | {'a': 4, 'c': 2} | | fish | None | [4 rows x 2 columns] | user | new name | | 3 | [5] | | 1 | [2, 3, 4] | | 2 | [6, 4, 5] | | 4 | [2, 3] | [4 rows x 2 columns] """

        if (type(column_names) != str and len(column_names) != 2):
            raise TypeError("'column_names' parameter has to be either a string or a list of two strings.")

        with cython_context():
            if type(column_names) == str:
                key_columns = [i for i in self.column_names() if i != column_names]
                if new_column_name is not None:
                    return self.groupby(key_columns, {new_column_name : aggregate.CONCAT(column_names)})
                else:
                    return self.groupby(key_columns, aggregate.CONCAT(column_names))
            elif len(column_names) == 2:
                key_columns = [i for i in self.column_names() if i not in column_names]
                if new_column_name is not None:
                    return self.groupby(key_columns, {new_column_name: aggregate.CONCAT(column_names[0], column_names[1])})
                else:
                    return self.groupby(key_columns, aggregate.CONCAT(column_names[0], column_names[1]))