Как запретить столбцам быть десятичными в DataFrames при извлечении из Postgres

У меня есть DataFramedf, который я получил из базы данных Postgres следующим образом.

using DataFrames, LibPQ

con = LibPQ.Connection(con_string)
result = execute(con, "SELECT * FROM [table]")
df = DataFrame(result)
close(con)

Извините, я не могу сделать это воспроизводимым.

Теперь либо DataFrames, либо LibPQ превращает столбцы NUMERIC Postgres в тип Decimals.Decimal. Это может быть круто для максимальной точности, но это создает проблемы, когда я пытаюсь построить что-либо с этими столбцами.

eltype.(eachcol(df))

5-element Vector{Union}:
 Union{Missing, String}
 Union{Missing, TimeZones.ZonedDateTime}
 Union{Missing, Int32}
 Union{Missing, Date}
 Union{Missing, Decimals.Decimal}

Как очень хорошо объяснил здесь Богумил Камински, я могу изменить столбцы определенного типа на другой тип. Предостережение в том, что я не могу даже проверить, относится ли столбец к типу Union{Missing, Decimals.Decimal}, потому что пакет Decimals не загружен. Ладно, подумал я, давайте тогда загрузим пакет Decimals - но не получается, потому что сначала нужно установить пакет...

Есть ли другой способ превратить эти столбцы в Float64s? Без установки всего пакета? Я знаю, что могу изменить типы столбцов, используя имена столбцов, например

df.my_column = Float64.(df.my_column)

но я не буду знать соответствующие имена столбцов заранее.

Вы можете использовать Union{Missing, AbstractFloat} в качестве селектора типа, как Decimal <: AbstractFloat.

Bogumił Kamiński 01.04.2022 11:40

Черт возьми, ты прав. Почему я не подумал об этом! Хочешь сделать это ответом?

Georgery 01.04.2022 11:48
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать Union{Missing, AbstractFloat} в качестве селектора типа, как Decimal <: AbstractFloat.

Поскольку Union{Missing, AbstractFloat} не является конкретным типом, вам нужно написать eltype(col) <: Union{Missing, AbstractFloat}, чтобы проверить условие подтипа.


Кстати, если у вас установлен LibPQ.jl, то у вас также есть доступ к Decimals.jl:

julia> LibPQ.Decimals.Decimal
Decimals.Decimal

Хм, я с таким энтузиазмом согласился, но теперь, когда я попробовал это, я понял, что на самом деле это не работает. Выполнение mapcols(df) do col eltype(col) === Union{Missing, AbstractFloat} ? Float64.(col) : col end не преобразует ни один из столбцов.

Georgery 01.04.2022 12:16

Я добавил обновление === проверки на точное равенство типов.

Bogumił Kamiński 01.04.2022 12:18

Хорошо, извините, что не понял, но == тоже не работает.

Georgery 01.04.2022 12:23

Вам нужно использовать <:, а не ==. <: проводит тест на подтип. (см. обновление в моем ответе)

Bogumił Kamiński 01.04.2022 12:25

Я добавил комментарий о том, как вы можете получить доступ к Decimals.jl, не добавляя его, если у вас уже есть LibPQ.jl в вашем Project.toml.

Bogumił Kamiński 01.04.2022 12:33

Вы можете использовать identity, чтобы правильно ввести каждый столбец в DataFrame.

julia> df=DataFrame(A=Number[1,2],B=Union{Missing,AbstractFloat}[3,4])
2×2 DataFrame
 Row │ A       B          
     │ Number  Abstract…? 
─────┼────────────────────
   1 │      1         3.0
   2 │      2         4.0

julia> identity.(df)
2×2 DataFrame
 Row │ A      B       
     │ Int64  Float64 
─────┼────────────────
   1 │     1      3.0
   2 │     2      4.0

Я не думаю, что это сработает в данном случае, так как цель состоит не просто в том, чтобы получить самый узкий тип значений, а в том, чтобы преобразовать их в другой тип.

Milan Bouchet-Valat 06.04.2022 22:50

Вопрос заключается в том, чтобы преобразовать в Float64, но, поскольку он говорит: «Это создает проблемы, когда я пытаюсь построить что-либо с этими столбцами», я ответил, как преобразовать в тип, который можно построить. Это полезно, потому что его можно записать коротко, если достаточно преобразования в самый узкий тип вместо преобразования в конкретный другой тип.

91 dokudo 08.04.2022 00:00

Другие вопросы по теме