Не удается сохранить фрейм данных pandas в паркет со списками поплавков в качестве значения ячейки

#python #pandas #parquet #pyarrow

Вопрос:

У меня есть фрейм данных со структурой, подобной этой:

                                                 Coumn1                                             Coumn2
0    (0.00030271668219938874, 0.0002655923890415579...  (0.0016430083196610212, 0.0014970217598602176,...
1    (0.00015607803652528673, 0.0001314736582571640...  (0.0022136708721518517, 0.0014974646037444472,...
2    (0.011317798867821693, 0.011339936405420303, 0...  (0.004868391435593367, 0.004406007472425699, 0...
3    (3.94578673876822e-05, 3.075833956245333e-05, ...  (0.0075020878575742245, 0.0096737677231431, 0....
4    (0.0004926157998852432, 0.0003811710048466921,...  (0.010351942852139473, 0.008231297135353088, 0...
..                                                 ...                                                ...
130  (0.011190211400389671, 0.011337820440530777, 0...  (0.010182800702750683, 0.011351295746862888, 0...
131  (0.006286659277975559, 0.007315031252801418, 0...  (0.02104150503873825, 0.02531484328210354, 0.0...
132  (0.0022791570518165827, 0.0025983047671616077,...  (0.008847278542816639, 0.009222050197422504, 0...
133  (0.0007059817435219884, 0.0009831463685259223,...  (0.0028264704160392284, 0.0029402063228189945,...
134  (0.0018992726691067219, 0.002058899961411953, ...  (0.0019639385864138603, 0.002009353833273053, ...

[135 rows x 2 columns]
 

где каждая ячейка содержит список/кортеж некоторых значений с плавающей запятой:

 type(psd_res.data_frame['Column1'][0])
<class 'tuple'>
type(psd_res.data_frame['Column1'][0][0])
<class 'numpy.float64'>
 

(каждая запись ячейки содержит одинаковое количество записей в кортеже)

когда я пытаюсь сохранить фрейм данных сейчас как паркет, я получаю ошибку (fastparquet):

 Can't infer object conversion type: 0    (0.00030271668219938874, 0.0002655923890415579...
1    (0.00015607803652528673, 0.0001314736582571640...
...

Name: Column1, dtype: object
 

Полная трассировка стека: https://pastebin.com/8Myu8hNV

и я также попробовал это с другим двигателем pyarrow:

 pyarrow.lib.ArrowInvalid: ('Could not convert (0.00030271668219938874, ..., 0.0002464042045176029)
  with type tuple: did not recognize Python value type when inferring an Arrow data type', 
  'Conversion failed for column UO-Pumpe with type object')
 

Итак, я нашел эту тему https://github.com/dask/fastparquet/issues/458. Похоже, это ошибка в fastparquet, но она должна работать в pyarrow, что для меня не работает.

Затем я попробовал некоторые вещи, которые мне понравились infer_objects() , и astype(float) … пока ничего не работало.

У кого-нибудь есть решение, как я могу сохранить свой фрейм данных в паркет?

Ответ №1:

Ячейки вашего фрейма данных содержат кортежи с плавающей точкой. Это необычный тип данных.

Поэтому вам нужно немного помочь arrow, чтобы определить тип ваших данных. Для этого вам необходимо четко указать схему вашей таблицы.

 df = pd.DataFrame(
    {
        "column1": [(1.0, 2.0), (3.0, 4.0, 5.0)]
    }
)
schema = pa.schema([pa.field('column1', pa.list_(pa.float64()))])
df.to_parquet('/tmp/hello.pq', schema=schema)
 

Обратите внимание, что если бы вы использовали списки поплавков (вместо кортежей), это сработало бы:

 df = pd.DataFrame(
    {
        "column1": [[1.0, 2.0], [3.0, 4.0, 5.0]]
    }
)
df.to_parquet('/tmp/hello.pq')
 

Комментарии:

1. thx, попробую это завтра и дам несколько отзывов

2. просто попробовал. пришлось внести некоторые изменения, потому что панды сами преобразовали мой список списков в серию кортежей. Так что теперь я использую панд. Метод DataFrame.from_dict для хранения списков и со списками он работает, как вы упомянули. Поскольку у меня есть огромное количество данных, я также попробую метод схемы и посмотрю, какой из них будет более эффективным.