【问题标题】:Using Pandas .apply() method with a regex-based function将 Pandas .apply() 方法与基于正则表达式的函数一起使用
【发布时间】:2019-08-10 00:34:15
【问题描述】:

我正在尝试通过在具有数字作为字符串的列上应用函数来在数据框中创建一个新列。

我已经编写了函数来提取我想要的数字,并在单个字符串输入上对其进行了测试,并且可以确认它可以工作。

SEARCH_PATTERN = r'([0-9]{1,2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})'
def get_total_time_minutes(time_col, pattern=SEARCH_PATTERN):
    """Uses regex to parse time_col which is a string in the format 'd hh:mm:ss' to
    obtain a total time in minutes
    """
    days, hours, minutes, _ = re.match(pattern, time_col).groups()
    total_time_minutes = (int(days)*24 + int(hours))*60 + int(minutes)
    return total_time_minutes

#test that the function works for a single input
text = "2 23:24:46"
print(get_total_time_minutes(text))

输出:4284

#apply the function to the required columns
df['Minutes Available'] = df['Resource available (d hh:mm:ss)'].apply(get_total_time_minutes)

下图是我的数据框列的屏幕截图。 Screenshot of my dataframe 我的数据框的“可用资源 (d hh:mm:ss)”列是 Pandas 类型“o”(字符串,如果我的理解正确的话),并且具有以下格式的数据:“5 08:00:00” .但是,当我在其上调用 apply(get_total_time_minutes) 时,出现以下错误:

TypeError:预期的字符串或类似字节的对象

为了进一步说明,“可用资源”列是一个字符串,表示资源可用的总时间(以天、小时、分钟和秒为单位)。我想将该时间字符串转换为以分钟为单位的总时间,因此 get_total_time_minutes 函数中的正则表达式和算术。 – Sam Ezebunandu 刚刚

【问题讨论】:

  • 您能否添加数据框的示例行df
  • 尝试使用.applymap() 而不是.apply(),因为get_total_time_minutes() 旨在对列的每个单元格 进行操作;而不是将列本身作为向量。
  • 它似乎对我有用:``` >>> d = pd.DataFrame({"Resource available (d hh:mm:ss)": ["2 23:24:46 ","3 23:12:45"]}) >>> d['可用分钟数'] = d['可用资源 (d hh:mm:ss)'].apply(get_total_time_minutes) >>> d 可用资源(d hh:mm:ss) 可用分钟数 0 2 23:24:46 4284 1 3 23:12:45 5712 ``
  • 谢谢@AlexandreB。我添加了我的数据框的屏幕截图。
  • 嗨@JeremyHue。我添加了我的数据框的屏幕截图。

标签: python regex pandas


【解决方案1】:

这可能有点 hacky,因为它使用 datetime 库来解析日期,然后通过减去默认 epoch 将其转换为 Timedelta

>>> pd.to_datetime('2 23:48:30', format='%d %H:%M:%S') - pd.to_datetime('0', format='%S')
Out[47]: Timedelta('1 days 23:48:30')

>>> Out[47] / pd.Timedelta('1 minute')
Out[50]: 2868.5

但它确实会告诉您这两天过去了多少分钟以及多少小时。它也是矢量化的,因此您可以将其应用于列并比使用 apply 更快地获取分钟值。

【讨论】:

  • TIL Out 对象。
  • 如果你在处理大数据,它也可能是一个真正的内存消耗
  • 该列实际上是以天为单位的时间增量,小时:分钟:秒,而不是时间戳。
  • 如果您的列已经是pd.Timedelta,那么只需将列除以pd.Timedelta('1 minute')
  • 谢谢,@ifly6 这行得通!我可以摆脱复杂的正则表达式并保持简单。
猜你喜欢
  • 1970-01-01
  • 2021-11-28
  • 2023-04-06
  • 1970-01-01
  • 2015-12-18
  • 2016-12-29
  • 2011-06-19
  • 2012-06-23
  • 1970-01-01
相关资源
最近更新 更多