-
Notifications
You must be signed in to change notification settings - Fork 183
Open
Description
/type feature
Hi, since TF records are already converted to Pyarrow Tables to compute statistics, how hard would it be to add an option to read directly Pyarrow file or Parquet file?
| | 'DecodeData' >> tf_example_decoder.DecodeTFExample( |
If my understanding of that code is correct we could replace beam.io.textio.ReadFromText by beam.io.parquetio.ReadFromParquet? if so will we need to extract features or the Pyarrow schema would be enough ?
My aim would be to use TFDV to extract data features and visualise them using facets.
Thanks
sethcoast
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
gowthamkpr commentedon Oct 9, 2019
In this issue, its mentioned that the Towards the goal of adding support for computing statistics over structured data (e.g., arbitrary protocol buffers, parquet data), GenerateStatistics API will take Arrow tables as input instead of Dict[FeatureName, ndarray]
caveness commentedon Oct 9, 2019
One thing to note is that the GenerateStatisticsAPI will only accept Arrow tables whose columns are ListArray of primitive types (e.g., int8, int16, int32, int64, uint8, uint16, uint32, uint64, float16, float32, float64, binary, string, unicode), so Arrow tables that are not in that format will not work with the API.
tanguycdls commentedon Oct 10, 2019
Hi thanks for the prompt answer ! Sorry I did not search enough before sending the issue.
About the limitation of the input data to Arrow Tables of ListArray of primitives: It does not include List of List dtypes? If I use those dtypes what can I do ?
When converted to TfRecords it seems it worked when printing the facets: I had access to the quantiles of length of the records.
jlafaye commentedon Feb 1, 2020
Many people use pandas or spark in their data preparation stage. Those tools dump parquet files in which every column is an array of 'primitive type', not an array of 'list of primitive types'.
I noticed that and tried to work around this limitation by attempting to cast between the two types but pyarrow does not support these kind of casts:
Traceback (most recent call last): File "apache_beam/runners/common.py", line 813, in apache_beam.runners.common.DoFnRunner.process File "apache_beam/runners/common.py", line 448, in apache_beam.runners.common.SimpleInvoker.invoke_process File "apache_beam/runners/common.py", line 928, in apache_beam.runners.common._OutputProcessor.process_outputs File "beam_test.py", line 64, in process yield table.cast(schema) File "pyarrow/table.pxi", line 1334, in itercolumns File "pyarrow/table.pxi", line 203, in pyarrow.lib.ChunkedArray.cast File "pyarrow/error.pxi", line 86, in pyarrow.lib.check_status pyarrow.lib.ArrowNotImplementedError: No cast implemented from int32 to list<item: int32>Just wanted to share my interest in this kind of feature. I would by happy to help if needed.
tanguycdls commentedon Mar 18, 2020
The following should work and not cost too much in terms of memory !
brills commentedon Mar 18, 2020
one caveat to that solution is that your original columns must not contain null (nil, None, etc).
tanguycdls commentedon Mar 19, 2020
Hi thanks for your answer indeed my dataframe was already null safe (replaced by 0) so i did not notice it...
So the easiest solution to use that would be to convert to TFrecords and let it handle all the conversions ?
If i can access the null mask of the array it should not be too hard to make the List array correctly but i'm not sure how to get it.
Thanks
brills commentedon Mar 19, 2020
I think there may be an easy patch to your existing solution so it handles Nulls correctly, but I'm not familiar with pandas APIs.
Basically, we want to translate something like pd.Series([1, 2, None, 3]) to pa.array([[1], [2], None, [3]))
Note that pa.array([1], [2], None, [3]) is essentially
So essentially, you can write a function that:
brills commentedon Mar 26, 2020
@tanguycdls : if you have something workable, do you mind making a contribution?
tanguycdls commentedon Mar 26, 2020
Hi @brills
I'm still struggling with the null handling.
An easy way of doing this would be to convert to pandas and retrieve the null mask but it would really costly for large datasets.
I found that script used in Fletcher (backend for arrow for Pandas): https://github.com/xhochy/fletcher/blob/9f50e39e378b7fa5d34616311e3207b395355bc2/fletcher/_algorithms.py#L70
I did not have time yet to go through it and merge all the pieces together, if I do I will share my code !
tanguycdls commentedon Mar 29, 2020
Hi, i worked a bit on the pyarrow side today: actually List Array does not have a mask parameter in the from_arrays function? are you running w/ a nightly version https://github.com/apache/arrow/blob/c49b960d2b697135c8de45222c6377e427ba8aad/python/pyarrow/array.pxi#L1402
To have null you need: offset[j] = None --> arr[j] = None
I did the following:
The to_pandas transformation is costly so still need to figure out how to avoid it!
EDIT i added the full example to use it directly in Beam:
https://gist.github.com/tanguycdls/0a1f7b928a27f9a4c5659f17d315999c
If you're interested i can make a pr out of it, it will be easier to check if all the cases are OK.
brills commentedon Mar 30, 2020
@tanguycdls
It's true that ListArray.from_arrays doesn't accept a mask parameter, but the offsets parameter actually serves two purposes:
if offset[i] == null, then arr[i] is null (but note that offset[i]'s value in the buffer still matters!)
https://github.com/apache/arrow/blob/0facdc77b7d3ddba5c2982a6ea8167ab12336a9a/cpp/src/arrow/array.cc#L241
So you should be able to do something like
you can use
tfx_bsl.arrow.array_util.GetArrayNullBitmapAsByteArrayinstead. (note that it's a private API in tfx_bsl, so I would encourage you to make a contribution if it works, to avoid depending on something that has no guarantees.)tanguycdls commentedon Mar 31, 2020
Thanks for the help @brills !
It simplifies a lot the code:
I will try to contribute that code as soon as I have more time on my side and once we're sure everything works well !
brills commentedon Mar 31, 2020
nice!
If you don't mind I can add this to tfx_bsl, and revise TFDV's generate_statistics_from_pyarrow. We recently find other libraries could also benefit from this adapter.
brills commentedon Apr 1, 2020
Sorry, I meant to revise generate_statistics_from_pandas. I could imagine a generate_statistics_from_pyarrow, but that will take longer (contributions are welcomed!)
tanguycdls commentedon Apr 2, 2020
Ok in that case i can try to contrib on the generate_statistics_from_parquet or pyarrow table, we are more interested by that use case and calling the private method seems to be a bad idea!
brills commentedon Apr 7, 2020
tensorflow/tfx-bsl@d6cc2b8 added the conversion function to tfx_bsl
khorshuheng commentedon Dec 7, 2020
@brills I created the generate_statistics_from_parquet method, based on the conversion function added to tfx_bsl:
https://gist.github.com/khorshuheng/4e0d305463a0cd5a5f7600706d619660
To verify the correctness, i compared the statistics generated from the above method, with
generate_statistics_from_csv. tfdv version is 0.25.0, pyarrow version is 0.17.0. The training dataset comes from the tutorial example (https://storage.googleapis.com/artifacts.tfx-oss-public.appspot.com/datasets/chicago_data.zip).Most statistics are correct, apart from a slight discrepancy for histogram statistics for
trip_start_timestamp.Does the github gist above decode the parquet file correctly? Or are there additional postprocessing required?
brills commentedon Dec 8, 2020
The histogram is computed using an approximate algorithm and due to the nondeterministic nature of beam, the result may even change across runs. So if the diff is slight it could be expected.
khorshuheng commentedon Dec 9, 2020
@brills Thanks for the clarification. In that case, can i submit a pull request based on github gist which i submitted? Or is there more work which is required?
sethcoast commentedon Jul 1, 2021
@brills @khorshuheng Any update on when generate_statistics_from_parquet() will be officially added to tfdv? I could really benefit from it.
DavidFarago commentedon Sep 29, 2022
The
generate_statistics_from_arrow()above is not working for me: