如何在 Pandas DataFrame 列中打开连字符分隔的数字范围?

How do you unwrap hyphen separated number ranges in a Pandas DataFrame column?

我有一个 Pandas DataFrame,其中有一列包含逗号分隔的数字、& 符号分隔的数字和连字符分隔的数字范围...

Title   LLFCs     Red     Amber   Green
a       15, 18    11.65   2.86    1.89
b       16 & 19   9.08    2.93    1.53
c       112-114   6.45    2.54    1.64

我希望每个 'LLFC' 值都有自己的行,这意味着连字符(在本例中为 113)隐含的数字也必须展开。我理想的结果如下...

Title   LLFCs     Red     Amber   Green
a       15        11.65   2.86    1.89
a       18        11.65   2.86    1.89
b       16        9.08    2.93    1.53
b       19        9.08    2.93    1.53
c       112       6.45    2.54    1.64
c       113       6.45    2.54    1.64
c       114       6.45    2.54    1.64

除了解开连字符值之外,我目前有以下几行可以完成我需要的一切...

data1 = data1.assign(LLFCs=data1['LLFCs'].str.replace('-',', '))
data1 = data1.assign(LLFCs=data1['LLFCs'].str.replace(' & ',', '))
data1 = data1.assign(LLFCs=data1['LLFCs'].str.split(', ')).explode('LLFCs')

这段代码实现了以下...

Title   LLFCs     Red     Amber   Green
a       15        11.65   2.86    1.89
a       18        11.65   2.86    1.89
b       16        9.08    2.93    1.53
b       19        9.08    2.93    1.53
c       112       6.45    2.54    1.64
c       114       6.45    2.54    1.64

这显然不包括连字符包装的值,有人能帮我解决这个问题吗?

灵感来自这里numeric string to range

import re
data = '''Title   LLFCs     Red     Amber   Green
a       15, 18    11.65   2.86    1.89
b       16 & 19    9.08    2.93    1.53
c       112-114   6.45    2.54    1.64'''
arr = [[t for t in re.split(r"[ ][ ]+", l)] for l in data.split("\n")]
df = pd.DataFrame(arr[1:], columns=arr[0])

def f(x):
    x = re.sub(" ","", x)
    result = []
    for part in x.split(','):
        if "-" in part:
            a, b = part.split("-")
            a, b = int(a), int(b)
            result.extend(range(a, b + 1))
        elif "&" in part:
            a, b = part.split("&")
            result += [int(a), int(b)]
        else:
            a = int(part)
            result.append(a)
    return result

df = df.assign(LLFCs=lambda x: [f(curr) for curr in x["LLFCs"]]).explode("LLFCs")
print(df.to_string(index=False))

输出

Title LLFCs    Red Amber Green
    a    15  11.65  2.86  1.89
    a    18  11.65  2.86  1.89
    b    16   9.08  2.93  1.53
    b    19   9.08  2.93  1.53
    c   112   6.45  2.54  1.64
    c   113   6.45  2.54  1.64
    c   114   6.45  2.54  1.64

拆分列 LLFCs,并遍历结果 - 如果分隔符是 -,则创建一个数字范围。之后,您可以 explode:

df['LLFCs'] = [tuple(range(int(first),int(last)+1))
               if delimiter == "-" else (int(first), int(last)) 
               for a, delimiter, b 
               #note that the delimiter is wrapped in parentheses,
               #this keeps the delimiter as part of the extract
               in df.LLFCs.str.split("([,&-])")
              ]
df


Title   LLFCs          Red     Amber    Green
0   a   (15, 18)       11.65    2.86    1.89
1   b   (16, 19)        9.08    2.93    1.53
2   c   (112, 113, 114) 6.45    2.54    1.64

现在,你可以爆炸了:

df.explode("LLFCs")

Title   LLFCs   Red Amber   Green
0   a   15  11.65   2.86    1.89
0   a   18  11.65   2.86    1.89
1   b   16  9.08    2.93    1.53
1   b   19  9.08    2.93    1.53
2   c   112 6.45    2.54    1.64
2   c   113 6.45    2.54    1.64
2   c   114 6.45    2.54    1.64