Dataset.map throws pyarrow.lib.ArrowNotImplementedError when converting from list of empty lists
Opened by sanderland (closed)

## Describe the bug

Dataset.map throws pyarrow.lib.ArrowNotImplementedError: Unsupported cast from int64 to null using function cast_null when converting from a type of 'empty lists' to 'lists with some type'.

This appears to be due to the interaction of arrow internals and some assumptions made by datasets.

The bug appeared when binarizing some labels, and then adding a dataset which had all these labels absent (to force the model to not label empty strings such with anything)
Particularly the fact that this only happens in batched mode is strange.

## Steps to reproduce the bug
```python
import numpy as np
ds = Dataset.from_dict(
    {
        "text": ["the lazy dog jumps over the quick fox", "another sentence"],
        "label": [[], []],
    }
)
def mapper(features):
    features['label'] = [
        [0,0,0] for l in features['label']
    ]
    return features
ds_mapped = ds.map(mapper,batched=True)
```

## Expected results
Not crashing

## Actual results
```
../.venv/lib/python3.8/site-packages/datasets/arrow_dataset.py:2346: in map
    return self._map_single(
../.venv/lib/python3.8/site-packages/datasets/arrow_dataset.py:532: in wrapper
    out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs)
../.venv/lib/python3.8/site-packages/datasets/arrow_dataset.py:499: in wrapper
    out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs)
../.venv/lib/python3.8/site-packages/datasets/fingerprint.py:458: in wrapper
    out = func(self, *args, **kwargs)
../.venv/lib/python3.8/site-packages/datasets/arrow_dataset.py:2751: in _map_single
    writer.write_batch(batch)
../.venv/lib/python3.8/site-packages/datasets/arrow_writer.py:503: in write_batch
    arrays.append(pa.array(typed_sequence))
pyarrow/array.pxi:230: in pyarrow.lib.array
    ???
pyarrow/array.pxi:110: in pyarrow.lib._handle_arrow_array_protocol
    ???
../.venv/lib/python3.8/site-packages/datasets/arrow_writer.py:198: in __arrow_array__
    out = cast_array_to_feature(out, type, allow_number_to_str=not self.trying_type)
../.venv/lib/python3.8/site-packages/datasets/table.py:1675: in wrapper
    return func(array, *args, **kwargs)
../.venv/lib/python3.8/site-packages/datasets/table.py:1812: in cast_array_to_feature
    casted_values = _c(array.values, feature.feature)
../.venv/lib/python3.8/site-packages/datasets/table.py:1675: in wrapper
    return func(array, *args, **kwargs)
../.venv/lib/python3.8/site-packages/datasets/table.py:1843: in cast_array_to_feature
    return array_cast(array, feature(), allow_number_to_str=allow_number_to_str)
../.venv/lib/python3.8/site-packages/datasets/table.py:1675: in wrapper
    return func(array, *args, **kwargs)
../.venv/lib/python3.8/site-packages/datasets/table.py:1752: in array_cast
    return array.cast(pa_type)
pyarrow/array.pxi:915: in pyarrow.lib.Array.cast
    ???
../.venv/lib/python3.8/site-packages/pyarrow/compute.py:376: in cast
    return call_function("cast", [arr], options)
pyarrow/_compute.pyx:542: in pyarrow._compute.call_function
    ???
pyarrow/_compute.pyx:341: in pyarrow._compute.Function.call
    ???
pyarrow/error.pxi:144: in pyarrow.lib.pyarrow_internal_check_status
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   pyarrow.lib.ArrowNotImplementedError: Unsupported cast from int64 to null using function cast_null
pyarrow/error.pxi:121: ArrowNotImplementedError
```

## Workarounds

* Not using batched=True
* Using an np.array([],dtype=float) or similar instead of [] in the input
* Naming the output column differently from the input column


## Environment info
<!-- You can run the command `datasets-cli env` and copy-and-paste its output below. -->
- `datasets` version: 2.2.2
- Platform: Ubuntu
- Python version: 3.8
- PyArrow version: 8.0.0


Comments:
Hi @sanderland ! Thanks for reporting :) This is a bug, I opened a PR to fix it. We'll do a new release soon

In the meantime you can fix it by specifying in advance that the "label" are integers:
```python
import numpy as np

ds = Dataset.from_dict(
    {
        "text": ["the lazy dog jumps over the quick fox", "another sentence"],
        "label": [[], []],
    }
)
# explicitly say that the "label" type is int64, even though it contains only null values
ds = ds.cast_column("label", Sequence(Value("int64")))

def mapper(features):
    features['label'] = [
        [0,0,0] for l in features['label']
    ]
    return features

ds_mapped = ds.map(mapper,batched=True)
```