Issue: load_datasets on csv returns everything as a string 
State: closed
Labels: name: bug

## Describe the bug
If you use:

`conll_dataset.to_csv("ner_conll.csv")`

It will create a csv file with all of your data as expected, however when you load it with:

`conll_dataset = load_dataset("csv", data_files="ner_conll.csv")` 

everything is read in as a string. For example if I look at everything in 'ner_tags' I get back `['[3 0 7 0 0 0 7 0 0]', '[1 2]', '[5 0]']` instead of what I originally saved which was `[[3, 0, 7, 0, 0, 0, 7, 0, 0], [1, 2], [5, 0]]`

I think maybe there is something funky going on with the csv delimiter 

## Steps to reproduce the bug
```python
# Sample code to reproduce the bug
#load original conll dataset
orig_conll = load_dataset("conll2003")

#save original conll as a csv 
orig_conll.to_csv("ner_conll.csv")

#reload conll data as a csv
new_conll = load_dataset("csv", data_files="ner_conll.csv")`
```

## Expected results
A clear and concise description of the expected results.
I would expect the data be returned as the data type I saved it as. I.e. if I save a list of ints 
[[3, 0, 7, 0, 0, 0, 7, 0, 0]], I shouldnt get back a string ['[3 0 7 0 0 0 7 0 0]']
I also get back a string when I pass a list of strings ['EU', 'rejects', 'German', 'call', 'to', 'boycott', 'British', 'lamb', '.']

## Actual results
A list of strings `['[3 0 7 0 0 0 7 0 0]', '[1 2]', '[5 0]']`
A string "['EU' 'rejects' 'German' 'call' 'to' 'boycott' 'British' 'lamb' '.']"

## Environment info
<!-- You can run the command `datasets-cli env` and copy-and-paste its output below. -->
- `datasets` version: 1.18.3
- Platform: Linux-5.4.0-121-generic-x86_64-with-glibc2.17
- Python version: 3.8.13
- PyArrow version: 8.0.0


Hi @courtneysprouse, thanks for reporting.

Yes, you are right: by default the "csv" loader loads all columns as strings. 

You could tweak this behavior by passing the `feature` argument to `load_dataset`, but it is also true that currently it is not possible to perform some kind of casts, due to lacking of implementation in PyArrow. For example:
```python
import datasets

features = datasets.Features(
    {
        "tokens": datasets.Sequence(datasets.Value("string")),
        "ner_tags": datasets.Sequence(datasets.Value("int32")),
    }
)

new_conll = datasets.load_dataset("csv", data_files="ner_conll.csv", features=features)
```
gives `ArrowNotImplementedError` error:
```
/usr/local/lib/python3.7/dist-packages/pyarrow/error.pxi in pyarrow.lib.check_status()

ArrowNotImplementedError: Unsupported cast from string to list using function cast_list
```

On the other hand, if you just would like to save and afterwards load your dataset, you could use `save_to_disk` and `load_from_disk` instead. These functions preserve all data types.
```python
>>> orig_conll.save_to_disk("ner_conll")

>>> from datasets import load_from_disk

>>> new_conll = load_from_disk("ner_conll")
>>> new_conll
DatasetDict({
    train: Dataset({
        features: ['id', 'tokens', 'pos_tags', 'chunk_tags', 'ner_tags'],
        num_rows: 14042
    })
    validation: Dataset({
        features: ['id', 'tokens', 'pos_tags', 'chunk_tags', 'ner_tags'],
        num_rows: 3251
    })
    test: Dataset({
        features: ['id', 'tokens', 'pos_tags', 'chunk_tags', 'ner_tags'],
        num_rows: 3454
    })
})
>>> new_conll["train"][0]
{'chunk_tags': [11, 21, 11, 12, 21, 22, 11, 12, 0],
 'id': '0',
 'ner_tags': [3, 0, 7, 0, 0, 0, 7, 0, 0],
 'pos_tags': [22, 42, 16, 21, 35, 37, 16, 21, 7],
 'tokens': ['EU',
  'rejects',
  'German',
  'call',
  'to',
  'boycott',
  'British',
  'lamb',
  '.']}
>>> new_conll["train"].features
{'chunk_tags': Sequence(feature=ClassLabel(num_classes=23, names=['O', 'B-ADJP', 'I-ADJP', 'B-ADVP', 'I-ADVP', 'B-CONJP', 'I-CONJP', 'B-INTJ', 'I-INTJ', 'B-LST', 'I-LST', 'B-NP', 'I-NP', 'B-PP', 'I-PP', 'B-PRT', 'I-PRT', 'B-SBAR', 'I-SBAR', 'B-UCP', 'I-UCP', 'B-VP', 'I-VP'], id=None), length=-1, id=None),
 'id': Value(dtype='string', id=None),
 'ner_tags': Sequence(feature=ClassLabel(num_classes=9, names=['O', 'B-PER', 'I-PER', 'B-ORG', 'I-ORG', 'B-LOC', 'I-LOC', 'B-MISC', 'I-MISC'], id=None), length=-1, id=None),
 'pos_tags': Sequence(feature=ClassLabel(num_classes=47, names=['"', "''", '#', '$', '(', ')', ',', '.', ':', '``', 'CC', 'CD', 'DT', 'EX', 'FW', 'IN', 'JJ', 'JJR', 'JJS', 'LS', 'MD', 'NN', 'NNP', 'NNPS', 'NNS', 'NN|SYM', 'PDT', 'POS', 'PRP', 'PRP$', 'RB', 'RBR', 'RBS', 'RP', 'SYM', 'TO', 'UH', 'VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ', 'WDT', 'WP', 'WP$', 'WRB'], id=None), length=-1, id=None),
 'tokens': Sequence(feature=Value(dtype='string', id=None), length=-1, id=None)}
```

Hi @albertvillanova!

Thanks so much for your suggestions! That worked! 

> Hi @courtneysprouse, thanks for reporting.
> 
> Yes, you are right: by default the "csv" loader loads all columns as strings.
> 
> You could tweak this behavior by passing the `feature` argument to `load_dataset`, but it is also true that currently it is not possible to perform some kind of casts, due to lacking of implementation in PyArrow. For example:
> 
> ```python
> import datasets
> 
> features = datasets.Features(
>     {
>         "tokens": datasets.Sequence(datasets.Value("string")),
>         "ner_tags": datasets.Sequence(datasets.Value("int32")),
>     }
> )
> 
> new_conll = datasets.load_dataset("csv", data_files="ner_conll.csv", features=features)
> ```
> 
> gives `ArrowNotImplementedError` error:
> 
> ```
> /usr/local/lib/python3.7/dist-packages/pyarrow/error.pxi in pyarrow.lib.check_status()
> 
> ArrowNotImplementedError: Unsupported cast from string to list using function cast_list
> ```
> 
> On the other hand, if you just would like to save and afterwards load your dataset, you could use `save_to_disk` and `load_from_disk` instead. These functions preserve all data types.
> 
> ```python
> >>> orig_conll.save_to_disk("ner_conll")
> 
> >>> from datasets import load_from_disk
> 
> >>> new_conll = load_from_disk("ner_conll")
> >>> new_conll
> DatasetDict({
>     train: Dataset({
>         features: ['id', 'tokens', 'pos_tags', 'chunk_tags', 'ner_tags'],
>         num_rows: 14042
>     })
>     validation: Dataset({
>         features: ['id', 'tokens', 'pos_tags', 'chunk_tags', 'ner_tags'],
>         num_rows: 3251
>     })
>     test: Dataset({
>         features: ['id', 'tokens', 'pos_tags', 'chunk_tags', 'ner_tags'],
>         num_rows: 3454
>     })
> })
> >>> new_conll["train"][0]
> {'chunk_tags': [11, 21, 11, 12, 21, 22, 11, 12, 0],
>  'id': '0',
>  'ner_tags': [3, 0, 7, 0, 0, 0, 7, 0, 0],
>  'pos_tags': [22, 42, 16, 21, 35, 37, 16, 21, 7],
>  'tokens': ['EU',
>   'rejects',
>   'German',
>   'call',
>   'to',
>   'boycott',
>   'British',
>   'lamb',
>   '.']}
> >>> new_conll["train"].features
> {'chunk_tags': Sequence(feature=ClassLabel(num_classes=23, names=['O', 'B-ADJP', 'I-ADJP', 'B-ADVP', 'I-ADVP', 'B-CONJP', 'I-CONJP', 'B-INTJ', 'I-INTJ', 'B-LST', 'I-LST', 'B-NP', 'I-NP', 'B-PP', 'I-PP', 'B-PRT', 'I-PRT', 'B-SBAR', 'I-SBAR', 'B-UCP', 'I-UCP', 'B-VP', 'I-VP'], id=None), length=-1, id=None),
>  'id': Value(dtype='string', id=None),
>  'ner_tags': Sequence(feature=ClassLabel(num_classes=9, names=['O', 'B-PER', 'I-PER', 'B-ORG', 'I-ORG', 'B-LOC', 'I-LOC', 'B-MISC', 'I-MISC'], id=None), length=-1, id=None),
>  'pos_tags': Sequence(feature=ClassLabel(num_classes=47, names=['"', "''", '#', '$', '(', ')', ',', '.', ':', '``', 'CC', 'CD', 'DT', 'EX', 'FW', 'IN', 'JJ', 'JJR', 'JJS', 'LS', 'MD', 'NN', 'NNP', 'NNPS', 'NNS', 'NN|SYM', 'PDT', 'POS', 'PRP', 'PRP$', 'RB', 'RBR', 'RBS', 'RP', 'SYM', 'TO', 'UH', 'VB', 'VBD', 'VBG', 'VBN', 'VBP', 'VBZ', 'WDT', 'WP', 'WP$', 'WRB'], id=None), length=-1, id=None),
>  'tokens': Sequence(feature=Value(dtype='string', id=None), length=-1, id=None)}
> ```

It seems that by default, the 'csv' loader doesn’t load all columns as strings. When I load a column with numbers that start with 0, datasets removes the leading 0 and converts this column to an integer type. How can I set it to load all columns as strings?