chain(...funcs) {
        const mapped = [...this].map(({ group }) => group.chain(...funcs));
        return this.df.__newInstance__(
            [].concat(...mapped.map(group => group.toCollection())),
            mapped[0].listColumns()
        );
    }
Chain maps and filters functions on DataFrame by optimizing their executions.
If a function returns boolean, it's a filter. Else it's a map.
It can be 10 - 100 x faster than standard chains of .map() and .filter().
@param {...Function} funcs Functions to apply on the DataFrame rows taking the row as parameter.
@returns {DataFrame} A new DataFrame with modified rows.
@example
groupedDF.chain(
     (row, i) => (i === 0), // filter
     row => row.set('column1', 3),  // map
     row => row.get('column2') === '5' // filter
)