解析文本并获得小时数

时间:2017-06-08 09:10:21

标签: python nltk

我有一个pandas数据框,文字属性为

loc_id   text
1        'Monday: 8:30 AM \x96 5:30 PM,Tuesday: 8:30 AM \x96 5:30 PM,Wednesday: 8:30 AM \x96 5:30 PM,Thursday: 8:30 AM \x96 5:30 PM,Friday: 8:30 AM \x96 5:30 PM,Saturday: Closed,Sunday: Closed'
2         ''
3         'Monday: Open 24 hours,Tuesday: Open 24 hours,Wednesday: Open 24 hours,Thursday: Open 24 hours,Friday: Open 24 hours,Saturday: Open 24 hours,Sunday: Open 24 hours

它是一个文本数据,我想计算它打开时的总开放时间

loc_id      openingHours
1           45
2           NAN
3           168

我是文本挖掘的新手,所以不知道如何解析和转换它。文本只提到了这两种格式。

2 个答案:

答案 0 :(得分:1)

我认为您需要一些自然语言日期解析器,例如dateparser

  

dateparser提供了几乎可以轻松解析本地化日期的模块   网页上常见的任何字符串格式。

     
      
  • 以英语,西班牙语,荷兰语,俄语和20多种其他语言对日期进行通用解析,以及与语言无关的多种格式   方式。
  •   
  • 相关日期的通用解析,例如:'1分钟前','2周前','3个月,1周和1天前','2天','明天'。
  •   
  • 具有时区缩写或UTC偏移的日期的一般解析,例如:'2015年8月14日美国东部时间','2013年7月4日太平洋标准时间',2013年7月21日   晚上10:15 +0500'。
  •   
  • 支持非公历日历系统。请参阅支持的日历。
  •   
  • 广泛的测试覆盖率。
  •   

如果你需要解析它,那么就像@ason​​gtoruin所提议的那样,你必须使用正则表达式:

import re
opened_str = 'Monday: 8:30 AM \x96 5:30 PM,Tuesday: 8:30 AM \x96 5:30 PM,Wednesday: 8:30 AM \x96 5:30 PM,Thursday: 8:30 AM \x96 5:30 PM,Friday: 8:30 AM \x96 5:30 PM,Saturday: Closed,Sunday: Closed'

PARSE_RE = re.compile(r'(?P<DAY>Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday): (?P<WORKHOURS>(?P<OPEN>\d+:\d+ (:?AM|PM)) \x96 (?P<CLOSE>\d+:\d+ (:?AM|PM))|Closed|Open 24 hours)')

for item in PARSE_RE.findall(opened_str):
    print(item)

将打印:

('Monday', '8:30 AM \x96 5:30 PM', '8:30 AM', 'AM', '5:30 PM', 'PM')
('Tuesday', '8:30 AM \x96 5:30 PM', '8:30 AM', 'AM', '5:30 PM', 'PM')
('Wednesday', '8:30 AM \x96 5:30 PM', '8:30 AM', 'AM', '5:30 PM', 'PM')
('Thursday', '8:30 AM \x96 5:30 PM', '8:30 AM', 'AM', '5:30 PM', 'PM')
('Friday', '8:30 AM \x96 5:30 PM', '8:30 AM', 'AM', '5:30 PM', 'PM')
('Saturday', 'Closed', '', '', '', '')
('Sunday', 'Closed', '', '', '', '')

因此,您可以检查每个元组的第二第三索引的开启/关闭时间,或者 1st ,如果它已关闭。之后,您可以根据自己的喜好解析这些日期。

答案 1 :(得分:1)

这是针对您的问题的工作解决方案

下面给出的解释。

import re
from datetime import datetime
sumtime = 0
sumlist=[]
list_of_strings = ['''Monday: 8:30 AM \x96 5:30 PM,Tuesday: 8:30 AM \x96 5:30 PM,Wednesday: 8:30 AM \x96 5:30 PM,Thursday: 8:30 AM
\x96 5:30 PM,Friday: 8:30 AM \x96 5:30 PM,Saturday: Closed,Sunday: Closed''','''Monday: Open 24 hours,Tuesday: Open 24 hours,Wednesday: Open
24 hours,Thursday: Open 24 hours,Friday: Open 24 hours,Saturday: Open 24 hours,Sunday: Open 24 hours''']

for s in list_of_strings: #Text for each loc_id
    if 'Open' not in s:
     #If the word 'Open' isn't present in the text then do below
            times = [line[0] for line in re.findall(r'\b((1[0-2]|0?[1-9]):([0-5][0-9]) ([AaPp][Mm]))',s)]
            times = [[i,j] for i,j in zip(times[0::2], times[1::2])]
            fmt = '%I:%M %p'
            time_objects = [datetime.strptime(b,fmt)-datetime.strptime(a,fmt)
                            for a,b in times]
            finaltime = [td.seconds//3600 for td in time_objects]
            sumtime=sum(finaltime)
            sumlist.append(sumtime)
    else:
    #If Open is present in the text 

            open_times = [int(st) for st in s.split() if st.isdigit()]
            sumlist.append(sum(open_times))
print(sumlist)

1) re.findall 返回字符串中找到的每个匹配项。它的输出将是这样的

[('8:30 AM', '8', '30', 'AM'),('5:30 PM', '5', '30', 'PM'), ('8:30 AM', '8', '30', 'AM')]

因此,行[0]将从元组中给出第一个。即'8:30 AM',我们需要

[line[0] for line in re.findall(r'\b((1[0-2]|0?[1-9]):([0-5][0-9]) ([AaPp][Mm]))',s)]

2)以上的输出将是

['8:30 AM', '5:30 PM', '8:30 AM', '5:30 PM', '8:30 AM', '5:30 PM', '8:30 AM', '5:30 PM', '8:30 AM', '5:30 PM']

3)现在列表中的每个偶数元素(0,2,4,...)将与奇数元素(1,3,5,...)配对。注意时间[0 :: 2]这里给出了一个元素列表,从索引0 开始,每个索引递增 2 。同样从索引1 开始 递增 2 。将它们压缩在一起。你明白了,

[['8:30 AM', '5:30 PM'], ['8:30 AM', '5:30 PM'],...and so on]

times = [[i,j] for i,j in zip(times[0::2], times[1::2])]

4)fmt是格式 fmt = '%I:%M %p'。请注意,它将是%H:%M,但因为我们使用的是%p 文件明确规定,在这种情况下,我们应该%I而不是%H。否则%H就好了。在我们的a,b [8:30 AM', '5:30 PM']上使用 datetime.strptime 来获取日期时间对象。减去它们以获得 timedelta 对象。使用timdelta_object.seconds将其转换为秒。

 [datetime.strptime(b,fmt)-datetime.strptime(a,fmt) for a,b in times]

然后,您可以使用td.days获取日期,td//3600获取时间

5)使用sum(your_list)查找此列表的总和,以获得您的案例中 45 的总和。将其附加到列表中。

6)如果文字中有 Open 这个词,

然后从文本中单独获取数字作为int并找到它们的总和。

7)最后输出列表将是

[45, 168]

这是解决您手头问题的有效方法。假设您以这种格式获得文本

'Monday: 8:30 AM \x96 5:30 PM,Tuesday: 8:30 AM \x96 5:30 PM,Wednesday: 8:30 AM \x96 5:30 PM,Thursday: 8:30 AM \x96 5:30 PM,Friday: 8:30 AM \x96 5:30 PM,Saturday: Closed,Sunday: Closed'

或此格式

'Monday: Open 24 hours,Tuesday: Open 24 hours,Wednesday: Open 24 hours,Thursday: Open 24 hours,Friday: Open 24 hours,Saturday: Open 24 hours,Sunday: Open 24 hours'

同时请务必查看dateparser