cast_column to Sequence with length=4 occur exception raise in datasets/table.py:2146
Opened by neiblegy (closed)

### Describe the bug

i load a dataset from local csv file which has 187383612 examples, then use `map` to generate new columns for test.
here is my code : 

```
import os

from datasets import load_dataset
from datasets.features import Sequence, Value

def add_new_path(example):

    example["ais_bbox"] = [100,100,200,200]
    example["ais_image_path"] = os.path.join("images", example["image_path"]) if example["image_path"] else ""
    return example

ais_dataset = load_dataset("/data/ryan.gao/ais_dataset_cache/raw/1749/")
hf_ds = ais_dataset.map(add_new_path, batched=False, num_proc=32)
ds = hf_ds.cast_column("ais_bbox", Sequence(Value("int32"), length=4))
```

and the `cast_column` raise an exception
```
Casting the dataset:   3%|███▉
...
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 2110, in cast_column
    return self.cast(features)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 2055, in cast
    dataset = dataset.map(
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 592, in wrapper
    out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 557, in wrapper
    out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 3097, in map
    for rank, done, content in Dataset._map_single(**dataset_kwargs):
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 3474, in _map_single
    batch = apply_function_on_filtered_inputs(
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 3353, in apply_function_on_filtered_inputs
    processed_inputs = function(*fn_args, *additional_args, **fn_kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2329, in table_cast
    return cast_table_to_schema(table, schema)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2288, in cast_table_to_schema
    arrays = [cast_array_to_feature(table[name], feature) for name, feature in features.items()]
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2288, in <listcomp>
    arrays = [cast_array_to_feature(table[name], feature) for name, feature in features.items()]
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1831, in wrapper
    return pa.chunked_array([func(chunk, *args, **kwargs) for chunk in array.chunks])
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1831, in <listcomp>
    return pa.chunked_array([func(chunk, *args, **kwargs) for chunk in array.chunks])
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2145, in cast_array_to_feature
    raise TypeError(f"Couldn't cast array of type\n{array.type}\nto\n{feature}")
TypeError: Couldn't cast array of type
list<item: int64>
to
Sequence(feature=Value(dtype='int32', id=None), length=4, id=None)
```
i check the source code and make debug info:
in datasets/table.py:2092
```
2091             if feature.length > -1:
2092                 if feature.length * len(array) == len(array.values):
2093                     return pa.FixedSizeListArray.from_arrays(_c(array.values, feature.feature), feature.length)
2094                 print(len(array))
2095                 print(len(array.values))
```
my feature.length is 4.  but feature.length * len(array) == len(array.values) is false.
print(len(array)) is 262
print(len(array.values)) is 4000

then I use "for item in array" to print each item then get 262 * [100,100,200,200]
and use "for item in array.values" to print each item and get 4000 int32 which are 1000 * [100,100,200,200]

i'm wondering the `chunk` in each `array.chunks`, the "chunk.values" may get all the chunks's value rather than single chunk? but i check the pyarrow's doc seems chunk.values is chunk's value not all.

### Steps to reproduce the bug

code provided above.

### Expected behavior

feature.length * len(array) == len(array.values) should be true. and there should not has Exception.

### Environment info

python3.9
x86_64
datasets: 2.14.4
pyarrow: 13.0.0 or 10.0.0

Comments:
Thanks for reporting! We've spotted the bugs with the `array.values` handling and are fixing them in https://github.com/huggingface/datasets/pull/6283 (should be part of the next release).

> Thanks for reporting! We've spotted the bugs with the `array.values` handling and are fixing them in #6283 (should be part of the next release).

i encounter another exception while cast_column to type `Sequence(feature={"points": Array2D(shape=(-1, 2), dtype="int64"), "label": ClassLabel(num_classes=num_classes, names=names)})`

while my data like this: '{"points": [[0.6,0.6], [0.7,0.7], [0.8,0.8]], "label": "A1"}'

here is the backtrace info:

```
    out = func(dataset, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 2110, in cast_column
    return self.cast(features)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 2055, in cast
    dataset = dataset.map(
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 592, in wrapper
    out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 557, in wrapper
    out: Union["Dataset", "DatasetDict"] = func(self, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 3097, in map
    for rank, done, content in Dataset._map_single(**dataset_kwargs):
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 3474, in _map_single
    batch = apply_function_on_filtered_inputs(
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/arrow_dataset.py", line 3353, in apply_function_on_filtered_inputs
    processed_inputs = function(*fn_args, *additional_args, **fn_kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2329, in table_cast
    return cast_table_to_schema(table, schema)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2288, in cast_table_to_schema
    arrays = [cast_array_to_feature(table[name], feature) for name, feature in features.items()]
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2288, in <listcomp>
    arrays = [cast_array_to_feature(table[name], feature) for name, feature in features.items()]
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1831, in wrapper
    return pa.chunked_array([func(chunk, *args, **kwargs) for chunk in array.chunks])
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1831, in <listcomp>
    return pa.chunked_array([func(chunk, *args, **kwargs) for chunk in array.chunks])
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2073, in cast_array_to_feature
    arrays = [_c(array.field(name), subfeature) for name, subfeature in feature.items()]
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2073, in <listcomp>
    arrays = [_c(array.field(name), subfeature) for name, subfeature in feature.items()]
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1833, in wrapper
    return func(array, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2095, in cast_array_to_feature
    casted_values = _c(array.values, feature.feature)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1833, in wrapper
    return func(array, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 2144, in cast_array_to_feature
    return array_cast(array, feature(), allow_number_to_str=allow_number_to_str)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1833, in wrapper
    return func(array, *args, **kwargs)
  File "/home/protoss.gao/.local/lib/python3.9/site-packages/datasets/table.py", line 1967, in array_cast
    return pa_type.wrap_array(array)
  File "pyarrow/types.pxi", line 1369, in pyarrow.lib.BaseExtensionType.wrap_array
TypeError: Incompatible storage type for extension<arrow.py_extension_type<Array2DExtensionType>>: expected list<item: list<item: double>>, got list<item: double>
```
and i print(array) in datasets/table.py:1967 indeed get 2D list. is that same issue in #6283 ?

besides this, hugging face datasets seems don't  naturally support multi-labels which means `Sequence(ClassLabel)` illegal if data is ["label1", "label2"]. so i have to define a class derived from `ClassLabel`, like this:

```
class AisClassLabels(ClassLabel):
    def encode_example(self, example_data):
        if self.num_classes is None:
            raise ValueError(
                "Trying to use ClassLabel feature with undefined number of class. "
                "Please set ClassLabel.names or num_classes."
            )
        if not isinstance(example_data, list):
            example_data = [example_data]

        for i in range(len(example_data)):
            if isinstance(example_data[i], str):
                example_data[i] = self.str2int(example_data[i])
                if not -1 <= example_data[i] < self.num_classes:
                    raise ValueError(f"Class label {example_data:d} greater than configured num_classes {self.num_classes}")
        return example_data
```
and it works well in my case. but is there any recommend way to implement multi-labels?

`Incompatible storage type for extension<arrow.py_extension_type<Array2DExtensionType>>: expected list<item: list<item: double>>, got list<item: double>`
if i change `Array2D(shape=(-1, 2), dtype="int64")` to `Sequence(Value("int64"))` , every thing goes well. but my data is 2D int list

i test Sequence(ClassLabel) is ok if one column is label list. but it is not ok in nested column such as `Sequence(feature= {"points": Sequence(Value("int32")), "label": Sequence(ClassLabel(num_classes....)))`. in this case i need override ClassLabels. encode_example as i given above.