Превратите строковое представление интервала в фактический интервал в пандах

Моя проблема довольно проста, но я не уверен, что есть способ сделать то, что я ищу:

Мне пришлось хранить в базе данных SQL некоторые данные, включая некоторые интервалы, которые позже будут использоваться. Из-за этого мне пришлось хранить его в виде строки, например:

 variable     interval
    A          (-0.001, 2.0]
    A          (2.0, 6.0]

Итак, я хочу использовать указанные интервалы для вырезания другой переменной, например:

df1 =  pd.DataFrame({'interval': {4: '(-0.001, 2.0]',
  5: '(2.0, 6.0]'},
 'variable': {4: 'A',
  5: 'A',
}})
df2 =  pd.DataFrame({'A': [1,1,3]})
bins = df1[df1.variable.eq('A')].interval
new_series = pd.cut(df2['A'], bins=bins)

Но это приносит:

 ValueError: could not convert string to float: '(-0.001, 2.0]'
 

Пытался:

bins = bins.astype('interval')

Но это приносит:

TypeError: type <class 'str'> with value (-0.001, 2.0] is not an interval

Я могу что-то сделать? Спасибо

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
2 267
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

IIUC, вы можете проанализировать строку вручную, а затем преобразовать бины в IntervalIndex:

import ast

import pandas as pd


def interval_type(s):
    """Parse interval string to Interval"""
    
    table = str.maketrans({'[': '(', ']': ')'})
    left_closed = s.startswith('[')
    right_closed = s.endswith(']')

    left, right = ast.literal_eval(s.translate(table))

    t = 'neither'
    if left_closed and right_closed:
        t = 'both'
    elif left_closed:
        t = 'left'
    elif right_closed:
        t = 'right'

    return pd.Interval(left, right, closed=t)


df1 = pd.DataFrame({'interval': {4: '(-0.001, 2.0]', 5: '(2.0, 6.0]'},
                    'variable': {4: 'A', 5: 'A'}})
df1['interval'] = df1['interval'].apply(interval_type)

df2 = pd.DataFrame({'A': [1, 1, 3]})
bins = df1[df1.variable.eq('A')].interval
new_series = pd.cut(df2['A'], bins=pd.IntervalIndex(bins))

print(new_series)

Выход

0    (-0.001, 2.0]
1    (-0.001, 2.0]
2       (2.0, 6.0]
Name: A, dtype: category
Categories (2, interval[float64]): [(-0.001, 2.0] < (2.0, 6.0]]

Большое спасибо! думал, что есть более прямой способ разбора, и теперь мне неловко из-за того, что вы написали это для меня.

Juan C 14.12.2020 21:48

Нет проблем, с каждым ответом, который я пишу, я немного узнаю.

Dani Mesejo 14.12.2020 21:50

Нас двое!

Juan C 14.12.2020 21:56

Это сработало почти на 100% для меня, но у меня есть несколько интервалов «inf», которые вызывают ValueError от ast. Кто-нибудь знает, как это исправить? ValueError: malformed node or string: <_ast.Name object at 0x7f3cbd48ae20> Где была строка: (1.0, inf]

Rômulo Férrer Filho 22.09.2022 23:30

@RômuloFérrerFilho и другие, способ - получить границы интервала вручную, например. используя: left, right = map(float, s.translate(table).replace('(', '').replace(')', '').split(', ')) вместо строки ast.literal_eval.

Stefan 25.10.2022 12:22

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