【问题标题】:seperate string number ranges in pandas dfpandas df 中的单独字符串编号范围
【发布时间】:2022-11-27 13:43:31
【问题描述】:

我有一个看起来像这样的 df

Type    range
Mike    10..13|7|8|
Ni      3..4
NANA    2|1|6

所需的输出应该是这样的

Type    range
Mike    10
Mike    11
Mike    12
Mike    13
Mike    7
Mike    8
Nico    3
Nico    4
NANA    2
NANA    1
NANA    6

因此,总计列预设了每种类型的多个值。范围值由两个number 和两个.. 分隔,一个值(无范围)在两个| | 之间显示

【问题讨论】:

  • 对于 Mike,您的第一个 df 中的范围是 10..15 但在您想要的输出中它只达到 13。为什么?另外,您的范围是排他性的还是包容性的(因此是否包括范围内的最后一个数字)?
  • 更正了范围及其包容性。

标签: python pandas


【解决方案1】:

假设您的范围是包容性的,我假设这是因为您的“3..4”转换为一行 3 和一行 4,并假设您忘记将 Mike 14 和 Mike 15 放入示例输出中,我发现以下解决方案:

import pandas as pd

def parse_str(s):
    numbers = []
    for v in s.rstrip('|').split('|'):
        if v.isdigit():
            numbers.append(int(v))
        else:
            start, end = v.split('..')
            numbers.extend(list(range(int(start), int(end)+1)))
    return pd.Series(numbers)

df.index = df['Type']
dfnew = df['range'].apply(parse_str).stack().reset_index(level=0).rename(columns={0: 'range'})

我们写了一个解析字符串的函数,就是把字符串按|拆分,如果字符串已经是数字,就把数字转成整数。否则,它是一个范围,所以我们再次按 .. 拆分并创建一个包含范围内所有数字的列表。最后,我们返回一个包含字符串中所有数字的 pd.Series。

然后,我们将该函数应用到带有df['range'].apply 的列并堆叠结果。为了确保我们仍然保留名称,我们必须首先将其设置为数据帧的索引。

【讨论】:

  • 它给我一个错误 KeyError: 'Type' on df.index = df['Type']
  • 我修复了错误,但现在它给了我一个ValueError: invalid literal for int() with base 10: '.414900'
  • 所以你不仅使用整数还使用浮点数?如果是这样的话,如果涉及浮点数,范围应该如何工作?
【解决方案2】:

你可以做

# split by '|' and explode
df = df.assign(range=df['range'].str.split('|')).explode('range')

# get the range(i, j) if the string has '..'
df['range'] = df['range'].apply(lambda r: range(int(r.split('..')[0]), int(r.split('..')[1])) if (len(r.split('..')) == 2) else r)

# explode
df = df.explode('range')
df

    Type    range
0   Mike       10
0   Mike       11
0   Mike       12
0   Mike       13
0   Mike       14
0   Mike        7
0   Mike        8
1     Ni        3
2   NANA        2
2   NANA        1
2   NANA        6

【讨论】:

  • 给我一个错误ValueError: invalid literal for int() with base 10: '613300|623510|644001|644003'
猜你喜欢
  • 2017-09-26
  • 2020-04-18
  • 1970-01-01
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
相关资源
最近更新 更多