Better list array values handling in cast/embed storage
State: closed | Author: mariosasko (COLLABORATOR)

Use [`array.flatten`](https://arrow.apache.org/docs/python/generated/pyarrow.ListArray.html#pyarrow.ListArray.flatten) that takes `.offset` into account instead of `array.values` in array cast/embed.

Comments: <details>
<summary>Show benchmarks</summary>

PyArrow==8.0.0

<details>
<summary>Show updated benchmarks!</summary>

### Benchmark: benchmark_array_xd.json

| metric | read_batch_formatted_as_numpy after write_array2d | read_batch_formatted_as_numpy after write_flattened_sequence | read_batch_formatted_as_numpy after write_nested_sequence | read_batch_unformated after write_array2d | read_batch_unformated after write_flattened_sequence | read_batch_unformated after write_nested_sequence | read_col_formatted_as_numpy after write_array2d | read_col_formatted_as_numpy after write_flattened_sequence | read_col_formatted_as_numpy after write_nested_sequence | read_col_unformated after write_array2d | read_col_unformated after write_flattened_sequence | read_col_unformated after write_nested_sequence | read_formatted_as_numpy after write_array2d | read_formatted_as_numpy after write_flattened_sequence | read_formatted_as_numpy after write_nested_sequence | read_unformated after write_array2d | read_unformated after write_flattened_sequence | read_unformated after write_nested_sequence | write_array2d | write_flattened_sequence | write_nested_sequence |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.008451 / 0.011353 (-0.002902) | 0.005056 / 0.011008 (-0.005952) | 0.086367 / 0.038508 (0.047859) | 0.068030 / 0.023109 (0.044920) | 0.358812 / 0.275898 (0.082914) | 0.385790 / 0.323480 (0.062310) | 0.005608 / 0.007986 (-0.002378) | 0.004262 / 0.004328 (-0.000067) | 0.066618 / 0.004250 (0.062368) | 0.053901 / 0.037052 (0.016849) | 0.398456 / 0.258489 (0.139967) | 0.391681 / 0.293841 (0.097840) | 0.046743 / 0.128546 (-0.081804) | 0.014118 / 0.075646 (-0.061528) | 0.308479 / 0.419271 (-0.110793) | 0.064214 / 0.043533 (0.020681) | 0.367940 / 0.255139 (0.112801) | 0.387204 / 0.283200 (0.104004) | 0.036093 / 0.141683 (-0.105590) | 1.534182 / 1.452155 (0.082027) | 1.598357 / 1.492716 (0.105641) |

### Benchmark: benchmark_getitem\_100B.json

| metric | get_batch_of\_1024\_random_rows | get_batch_of\_1024\_rows | get_first_row | get_last_row |
|--------|---|---|---|---|
| new / old (diff) | 0.265910 / 0.018006 (0.247904) | 0.589453 / 0.000490 (0.588963) | 0.004881 / 0.000200 (0.004681) | 0.000090 / 0.000054 (0.000036) |

### Benchmark: benchmark_indices_mapping.json

| metric | select | shard | shuffle | sort | train_test_split |
|--------|---|---|---|---|---|
| new / old (diff) | 0.032540 / 0.037411 (-0.004872) | 0.083153 / 0.014526 (0.068627) | 0.098960 / 0.176557 (-0.077597) | 0.162044 / 0.737135 (-0.575091) | 0.093602 / 0.296338 (-0.202736) |

### Benchmark: benchmark_iterating.json

| metric | read 5000 | read 50000 | read_batch 50000 10 | read_batch 50000 100 | read_batch 50000 1000 | read_formatted numpy 5000 | read_formatted pandas 5000 | read_formatted tensorflow 5000 | read_formatted torch 5000 | read_formatted_batch numpy 5000 10 | read_formatted_batch numpy 5000 1000 | shuffled read 5000 | shuffled read 50000 | shuffled read_batch 50000 10 | shuffled read_batch 50000 100 | shuffled read_batch 50000 1000 | shuffled read_formatted numpy 5000 | shuffled read_formatted_batch numpy 5000 10 | shuffled read_formatted_batch numpy 5000 1000 |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.517056 / 0.215209 (0.301847) | 5.167908 / 2.077655 (3.090253) | 2.359856 / 1.504120 (0.855736) | 2.092448 / 1.541195 (0.551253) | 2.100270 / 1.468490 (0.631780) | 0.742321 / 4.584777 (-3.842456) | 4.845010 / 3.745712 (1.099298) | 4.361808 / 5.269862 (-0.908054) | 2.621941 / 4.565676 (-1.943736) | 0.094907 / 0.424275 (-0.329369) | 0.009357 / 0.007607 (0.001750) | 0.719859 / 0.226044 (0.493814) | 6.929731 / 2.268929 (4.660802) | 3.240862 / 55.444624 (-52.203763) | 2.700817 / 6.876477 (-4.175659) | 2.904600 / 2.142072 (0.762527) | 0.924930 / 4.805227 (-3.880298) | 0.194390 / 6.500664 (-6.306274) | 0.078331 / 0.075469 (0.002862) |

### Benchmark: benchmark_map_filter.json

| metric | filter | map fast-tokenizer batched | map identity | map identity batched | map no-op batched | map no-op batched numpy | map no-op batched pandas | map no-op batched pytorch | map no-op batched tensorflow |
|--------|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 1.539347 / 1.841788 (-0.302441) | 22.696358 / 8.074308 (14.622050) | 18.791692 / 10.191392 (8.600300) | 0.221376 / 0.680424 (-0.459048) | 0.029824 / 0.534201 (-0.504377) | 0.455604 / 0.579283 (-0.123679) | 0.573169 / 0.434364 (0.138805) | 0.507109 / 0.540337 (-0.033228) | 0.730986 / 1.386936 (-0.655950) |

</details>
PyArrow==latest

<details>
<summary>Show updated benchmarks!</summary>

### Benchmark: benchmark_array_xd.json

| metric | read_batch_formatted_as_numpy after write_array2d | read_batch_formatted_as_numpy after write_flattened_sequence | read_batch_formatted_as_numpy after write_nested_sequence | read_batch_unformated after write_array2d | read_batch_unformated after write_flattened_sequence | read_batch_unformated after write_nested_sequence | read_col_formatted_as_numpy after write_array2d | read_col_formatted_as_numpy after write_flattened_sequence | read_col_formatted_as_numpy after write_nested_sequence | read_col_unformated after write_array2d | read_col_unformated after write_flattened_sequence | read_col_unformated after write_nested_sequence | read_formatted_as_numpy after write_array2d | read_formatted_as_numpy after write_flattened_sequence | read_formatted_as_numpy after write_nested_sequence | read_unformated after write_array2d | read_unformated after write_flattened_sequence | read_unformated after write_nested_sequence | write_array2d | write_flattened_sequence | write_nested_sequence |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.009308 / 0.011353 (-0.002045) | 0.005027 / 0.011008 (-0.005982) | 0.074094 / 0.038508 (0.035586) | 0.068277 / 0.023109 (0.045168) | 0.412716 / 0.275898 (0.136818) | 0.446883 / 0.323480 (0.123403) | 0.005864 / 0.007986 (-0.002122) | 0.003753 / 0.004328 (-0.000575) | 0.072575 / 0.004250 (0.068325) | 0.064434 / 0.037052 (0.027382) | 0.445395 / 0.258489 (0.186906) | 0.464520 / 0.293841 (0.170679) | 0.045303 / 0.128546 (-0.083243) | 0.013120 / 0.075646 (-0.062527) | 0.077830 / 0.419271 (-0.341441) | 0.057303 / 0.043533 (0.013770) | 0.420845 / 0.255139 (0.165706) | 0.431308 / 0.283200 (0.148109) | 0.033908 / 0.141683 (-0.107775) | 1.577667 / 1.452155 (0.125512) | 1.677321 / 1.492716 (0.184604) |

### Benchmark: benchmark_getitem\_100B.json

| metric | get_batch_of\_1024\_random_rows | get_batch_of\_1024\_rows | get_first_row | get_last_row |
|--------|---|---|---|---|
| new / old (diff) | 0.305855 / 0.018006 (0.287849) | 0.601442 / 0.000490 (0.600953) | 0.010722 / 0.000200 (0.010522) | 0.000158 / 0.000054 (0.000104) |

### Benchmark: benchmark_indices_mapping.json

| metric | select | shard | shuffle | sort | train_test_split |
|--------|---|---|---|---|---|
| new / old (diff) | 0.029202 / 0.037411 (-0.008209) | 0.094576 / 0.014526 (0.080050) | 0.106734 / 0.176557 (-0.069822) | 0.168114 / 0.737135 (-0.569021) | 0.107241 / 0.296338 (-0.189098) |

### Benchmark: benchmark_iterating.json

| metric | read 5000 | read 50000 | read_batch 50000 10 | read_batch 50000 100 | read_batch 50000 1000 | read_formatted numpy 5000 | read_formatted pandas 5000 | read_formatted tensorflow 5000 | read_formatted torch 5000 | read_formatted_batch numpy 5000 10 | read_formatted_batch numpy 5000 1000 | shuffled read 5000 | shuffled read 50000 | shuffled read_batch 50000 10 | shuffled read_batch 50000 100 | shuffled read_batch 50000 1000 | shuffled read_formatted numpy 5000 | shuffled read_formatted_batch numpy 5000 10 | shuffled read_formatted_batch numpy 5000 1000 |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.643634 / 0.215209 (0.428425) | 6.391757 / 2.077655 (4.314103) | 3.011679 / 1.504120 (1.507559) | 2.379711 / 1.541195 (0.838517) | 2.387444 / 1.468490 (0.918954) | 0.823460 / 4.584777 (-3.761317) | 4.882240 / 3.745712 (1.136528) | 4.091170 / 5.269862 (-1.178691) | 2.688761 / 4.565676 (-1.876915) | 0.094555 / 0.424275 (-0.329720) | 0.008464 / 0.007607 (0.000857) | 0.665949 / 0.226044 (0.439905) | 6.948237 / 2.268929 (4.679309) | 3.384894 / 55.444624 (-52.059730) | 2.675570 / 6.876477 (-4.200907) | 3.073045 / 2.142072 (0.930973) | 0.969780 / 4.805227 (-3.835447) | 0.205859 / 6.500664 (-6.294805) | 0.072548 / 0.075469 (-0.002922) |

### Benchmark: benchmark_map_filter.json

| metric | filter | map fast-tokenizer batched | map identity | map identity batched | map no-op batched | map no-op batched numpy | map no-op batched pandas | map no-op batched pytorch | map no-op batched tensorflow |
|--------|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 1.563869 / 1.841788 (-0.277919) | 22.431392 / 8.074308 (14.357084) | 19.434811 / 10.191392 (9.243419) | 0.255135 / 0.680424 (-0.425289) | 0.027799 / 0.534201 (-0.506402) | 0.427713 / 0.579283 (-0.151570) | 0.527030 / 0.434364 (0.092666) | 0.503660 / 0.540337 (-0.036678) | 0.730996 / 1.386936 (-0.655940) |

</details>
</details>

![](https://cml.dev/watermark.png#06c1940953807dbde4bc18af64bd3d87234edf00 "CML watermark")


<details>
<summary>Show benchmarks</summary>

PyArrow==8.0.0

<details>
<summary>Show updated benchmarks!</summary>

### Benchmark: benchmark_array_xd.json

| metric | read_batch_formatted_as_numpy after write_array2d | read_batch_formatted_as_numpy after write_flattened_sequence | read_batch_formatted_as_numpy after write_nested_sequence | read_batch_unformated after write_array2d | read_batch_unformated after write_flattened_sequence | read_batch_unformated after write_nested_sequence | read_col_formatted_as_numpy after write_array2d | read_col_formatted_as_numpy after write_flattened_sequence | read_col_formatted_as_numpy after write_nested_sequence | read_col_unformated after write_array2d | read_col_unformated after write_flattened_sequence | read_col_unformated after write_nested_sequence | read_formatted_as_numpy after write_array2d | read_formatted_as_numpy after write_flattened_sequence | read_formatted_as_numpy after write_nested_sequence | read_unformated after write_array2d | read_unformated after write_flattened_sequence | read_unformated after write_nested_sequence | write_array2d | write_flattened_sequence | write_nested_sequence |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.007597 / 0.011353 (-0.003756) | 0.004492 / 0.011008 (-0.006516) | 0.103779 / 0.038508 (0.065271) | 0.079287 / 0.023109 (0.056178) | 0.389651 / 0.275898 (0.113753) | 0.421955 / 0.323480 (0.098475) | 0.006023 / 0.007986 (-0.001963) | 0.003727 / 0.004328 (-0.000602) | 0.078604 / 0.004250 (0.074354) | 0.060810 / 0.037052 (0.023758) | 0.412170 / 0.258489 (0.153681) | 0.436218 / 0.293841 (0.142377) | 0.037282 / 0.128546 (-0.091264) | 0.010341 / 0.075646 (-0.065305) | 0.357652 / 0.419271 (-0.061620) | 0.063320 / 0.043533 (0.019788) | 0.389454 / 0.255139 (0.134315) | 0.433073 / 0.283200 (0.149874) | 0.028449 / 0.141683 (-0.113234) | 1.894107 / 1.452155 (0.441952) | 1.954190 / 1.492716 (0.461474) |

### Benchmark: benchmark_getitem\_100B.json

| metric | get_batch_of\_1024\_random_rows | get_batch_of\_1024\_rows | get_first_row | get_last_row |
|--------|---|---|---|---|
| new / old (diff) | 0.224477 / 0.018006 (0.206471) | 0.510878 / 0.000490 (0.510388) | 0.005013 / 0.000200 (0.004813) | 0.000092 / 0.000054 (0.000037) |

### Benchmark: benchmark_indices_mapping.json

| metric | select | shard | shuffle | sort | train_test_split |
|--------|---|---|---|---|---|
| new / old (diff) | 0.032976 / 0.037411 (-0.004436) | 0.101073 / 0.014526 (0.086547) | 0.113990 / 0.176557 (-0.062566) | 0.183499 / 0.737135 (-0.553636) | 0.114283 / 0.296338 (-0.182056) |

### Benchmark: benchmark_iterating.json

| metric | read 5000 | read 50000 | read_batch 50000 10 | read_batch 50000 100 | read_batch 50000 1000 | read_formatted numpy 5000 | read_formatted pandas 5000 | read_formatted tensorflow 5000 | read_formatted torch 5000 | read_formatted_batch numpy 5000 10 | read_formatted_batch numpy 5000 1000 | shuffled read 5000 | shuffled read 50000 | shuffled read_batch 50000 10 | shuffled read_batch 50000 100 | shuffled read_batch 50000 1000 | shuffled read_formatted numpy 5000 | shuffled read_formatted_batch numpy 5000 10 | shuffled read_formatted_batch numpy 5000 1000 |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.473242 / 0.215209 (0.258033) | 4.719800 / 2.077655 (2.642146) | 2.318732 / 1.504120 (0.814612) | 2.102336 / 1.541195 (0.561141) | 2.143618 / 1.468490 (0.675128) | 0.594122 / 4.584777 (-3.990654) | 4.265961 / 3.745712 (0.520249) | 3.794635 / 5.269862 (-1.475226) | 2.394506 / 4.565676 (-2.171170) | 0.070091 / 0.424275 (-0.354184) | 0.009222 / 0.007607 (0.001614) | 0.564496 / 0.226044 (0.338452) | 5.644348 / 2.268929 (3.375419) | 2.934395 / 55.444624 (-52.510229) | 2.429076 / 6.876477 (-4.447401) | 2.592010 / 2.142072 (0.449937) | 0.713371 / 4.805227 (-4.091856) | 0.165019 / 6.500664 (-6.335646) | 0.075913 / 0.075469 (0.000444) |

### Benchmark: benchmark_map_filter.json

| metric | filter | map fast-tokenizer batched | map identity | map identity batched | map no-op batched | map no-op batched numpy | map no-op batched pandas | map no-op batched pytorch | map no-op batched tensorflow |
|--------|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 1.570836 / 1.841788 (-0.270951) | 22.569763 / 8.074308 (14.495455) | 17.159658 / 10.191392 (6.968266) | 0.185716 / 0.680424 (-0.494708) | 0.021938 / 0.534201 (-0.512263) | 0.487204 / 0.579283 (-0.092079) | 0.472776 / 0.434364 (0.038412) | 0.565052 / 0.540337 (0.024714) | 0.763322 / 1.386936 (-0.623614) |

</details>
PyArrow==latest

<details>
<summary>Show updated benchmarks!</summary>

### Benchmark: benchmark_array_xd.json

| metric | read_batch_formatted_as_numpy after write_array2d | read_batch_formatted_as_numpy after write_flattened_sequence | read_batch_formatted_as_numpy after write_nested_sequence | read_batch_unformated after write_array2d | read_batch_unformated after write_flattened_sequence | read_batch_unformated after write_nested_sequence | read_col_formatted_as_numpy after write_array2d | read_col_formatted_as_numpy after write_flattened_sequence | read_col_formatted_as_numpy after write_nested_sequence | read_col_unformated after write_array2d | read_col_unformated after write_flattened_sequence | read_col_unformated after write_nested_sequence | read_formatted_as_numpy after write_array2d | read_formatted_as_numpy after write_flattened_sequence | read_formatted_as_numpy after write_nested_sequence | read_unformated after write_array2d | read_unformated after write_flattened_sequence | read_unformated after write_nested_sequence | write_array2d | write_flattened_sequence | write_nested_sequence |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.007810 / 0.011353 (-0.003543) | 0.005140 / 0.011008 (-0.005869) | 0.079018 / 0.038508 (0.040510) | 0.080899 / 0.023109 (0.057790) | 0.489213 / 0.275898 (0.213315) | 0.525334 / 0.323480 (0.201854) | 0.006992 / 0.007986 (-0.000994) | 0.003729 / 0.004328 (-0.000599) | 0.079277 / 0.004250 (0.075026) | 0.064883 / 0.037052 (0.027831) | 0.496718 / 0.258489 (0.238229) | 0.534976 / 0.293841 (0.241135) | 0.038790 / 0.128546 (-0.089756) | 0.010122 / 0.075646 (-0.065524) | 0.087669 / 0.419271 (-0.331603) | 0.057959 / 0.043533 (0.014426) | 0.490611 / 0.255139 (0.235472) | 0.518376 / 0.283200 (0.235176) | 0.026561 / 0.141683 (-0.115122) | 1.843241 / 1.452155 (0.391086) | 1.952367 / 1.492716 (0.459651) |

### Benchmark: benchmark_getitem\_100B.json

| metric | get_batch_of\_1024\_random_rows | get_batch_of\_1024\_rows | get_first_row | get_last_row |
|--------|---|---|---|---|
| new / old (diff) | 0.289799 / 0.018006 (0.271792) | 0.486999 / 0.000490 (0.486509) | 0.017481 / 0.000200 (0.017281) | 0.000122 / 0.000054 (0.000068) |

### Benchmark: benchmark_indices_mapping.json

| metric | select | shard | shuffle | sort | train_test_split |
|--------|---|---|---|---|---|
| new / old (diff) | 0.037662 / 0.037411 (0.000250) | 0.113238 / 0.014526 (0.098712) | 0.123918 / 0.176557 (-0.052638) | 0.190484 / 0.737135 (-0.546652) | 0.126473 / 0.296338 (-0.169865) |

### Benchmark: benchmark_iterating.json

| metric | read 5000 | read 50000 | read_batch 50000 10 | read_batch 50000 100 | read_batch 50000 1000 | read_formatted numpy 5000 | read_formatted pandas 5000 | read_formatted tensorflow 5000 | read_formatted torch 5000 | read_formatted_batch numpy 5000 10 | read_formatted_batch numpy 5000 1000 | shuffled read 5000 | shuffled read 50000 | shuffled read_batch 50000 10 | shuffled read_batch 50000 100 | shuffled read_batch 50000 1000 | shuffled read_formatted numpy 5000 | shuffled read_formatted_batch numpy 5000 10 | shuffled read_formatted_batch numpy 5000 1000 |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.530622 / 0.215209 (0.315413) | 5.292093 / 2.077655 (3.214438) | 2.819354 / 1.504120 (1.315234) | 2.609821 / 1.541195 (1.068626) | 2.680090 / 1.468490 (1.211600) | 0.603490 / 4.584777 (-3.981287) | 4.344541 / 3.745712 (0.598828) | 3.874001 / 5.269862 (-1.395861) | 2.445302 / 4.565676 (-2.120375) | 0.071173 / 0.424275 (-0.353102) | 0.009131 / 0.007607 (0.001524) | 0.627273 / 0.226044 (0.401229) | 6.278637 / 2.268929 (4.009709) | 3.433762 / 55.444624 (-52.010862) | 2.973400 / 6.876477 (-3.903077) | 3.188165 / 2.142072 (1.046093) | 0.722824 / 4.805227 (-4.082404) | 0.165154 / 6.500664 (-6.335510) | 0.075268 / 0.075469 (-0.000202) |

### Benchmark: benchmark_map_filter.json

| metric | filter | map fast-tokenizer batched | map identity | map identity batched | map no-op batched | map no-op batched numpy | map no-op batched pandas | map no-op batched pytorch | map no-op batched tensorflow |
|--------|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 1.652994 / 1.841788 (-0.188794) | 23.309030 / 8.074308 (15.234722) | 18.135649 / 10.191392 (7.944257) | 0.177543 / 0.680424 (-0.502881) | 0.024784 / 0.534201 (-0.509417) | 0.489952 / 0.579283 (-0.089331) | 0.485368 / 0.434364 (0.051004) | 0.580583 / 0.540337 (0.040246) | 0.787843 / 1.386936 (-0.599093) |

</details>
</details>

![](https://cml.dev/watermark.png#5982039f7814a204fe532240ca6aabe72430d834 "CML watermark")


_The documentation is not available anymore as the PR was closed or merged._

A bug in `FixedSizeArray.flatten` in `PyArrow<10.0.0` makes CI fail. Colab installs 9.0.0 by default, so we should be able to set the minimal version to `10.0.0` soon. Keeping this PR as a draft in the meantime.

Closing this PR in favor of https://github.com/huggingface/datasets/pull/6283