将 pandas 中的区间字符串表示转化为实际区间

4

我的问题比较简单,但我不确定有没有办法实现我想要的:

我需要将一些包含后续使用的时间间隔的数据存储在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

有什么我可以做的吗?谢谢

1个回答

8

如果我理解得没错的话,您可以手动解析字符串,然后将它们转换为区间索引:

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]]

1
非常感谢!我本以为有更简单的解析方法,现在让你为我写这个我感到很抱歉。 - Juan C
2
没问题,每次写答案我都会学到一点。 - Dani Mesejo
1
我们俩一样! - Juan C
1
那对我几乎百分之百有效,但是我有一些“inf”间隔,它们会从ast引发ValueError。有人知道如何修复吗?'ValueError: 节点或字符串格式错误:<_ast.Name object at 0x7f3cbd48ae20>'其中字符串为:(1.0, inf] - Rômulo Férrer Filho
@RômuloFérrerFilho 和其他人,一个解决方法是手动检索区间边界,例如使用:left, right = map(float, s.translate(table).replace('(', '').replace(')', '').split(', ')) 而不是 ast.literal_eval 行。 - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接