使用Python计算文件中条目之间的时间差
我有一个CSV文件,里面的数据格式是这样的:日期,时间,事件,用户,网络
。我需要逐行查看这个文件,如果事件是“开始”,就继续往下查,直到找到同一个用户和网络的“结束”事件,然后计算这两个事件之间的时间差。
我有这段代码:
import csv
import datetime
import time
with open('dates.csv', 'rb') as csv_file:
csv_read = csv.reader(csv_file)
for row in csv_read:
if row[2]=="start":
n1=datetime.datetime.strptime(row[1], '%H:%M:%S')
for row2 in csv_read:
if (row2[2]=="End" and row[3]==row2[3] and row[4]==row2[4]):
n2=datetime.datetime.strptime(row2[1], '%H:%M:%S')
print row[2],row[1], row2[2], row2[1]
diff = n2 - n1
print "time difference = ", diff.seconds
break
但是这段代码有个问题,就是当它找到“结束”并计算时间后,会从“结束”那一行的下一行开始查找,忽略了之前的行。举个例子:
May,20,9:02:22,2010,start,user1,net-3
May,20,9:02:23,2010,start,user1,net-3
May,20,9:02:55,2010,start,user1,net-2
May,20,9:02:55,2010,End,user1,net-3
May,20,9:03:43,2010,End,user1,net-2
May,20,9:02:55,2010,End,user1,net-3
May,20,9:03:43,2010,End,user1,net-2
May,20,9:03:44,2010,start,user1,net-2
May,20,9:03:49,2010,End,user1,net-2
这样只会产生以下输出:
Connect 9:02:22 Disconnect 9:02:55
time difference = 33
Connect 9:03:44 Disconnect 9:03:49
time difference = 5
所以有没有人知道怎么解决这个问题呢?另外,能不能把时间差作为额外的一列加到现有的数据里?
谢谢!
我更新了代码,但现在我遇到了一个新问题,我的文件有35734行,但输出文件只有350行,我搞不清楚为什么会这样,任何帮助都非常感谢!
更新后的代码:
l1=[] ## empty list
l2=[] ## empty list
csv_file=open('dates_read.csv', 'r+')
csv_wfile=open('dates_write.csv', 'w+')
csv_read = csv.reader(csv_file)
csv_read1 = csv_read
csv_write = csv.writer(csv_wfile)
for row in csv_read:
s=csv_read.line_num
if (row[4]=="start" and (s not in l1)):
n1=datetime.datetime.strptime(row[2], '%H:%M:%S')
l1.append(s)
month = str(row[0])
day = int(row[1])
time = str(row[2])
year = int(row[3])
user = str(row[5])
net = str(row[6])
dwell_time = str(row[7])
for row2 in csv_read1:
e=csv_read1.line_num
if (row2[4]=="End" and row[5]==row2[5] and row[6]==row2[6] and (csv_read1.line_num not in l2)and s<e):
n2=datetime.datetime.strptime(row2[2], '%H:%M:%S')
diff = n2 - n1
dwell_time= diff
print("time difference = ", diff.seconds,"\n")
csv_write.writerow([month, day, time, year, user, net, dwell_time])
l2.append(e)
break
print (s) #prints 818
print (e) #prints 35734
2 个回答
1
我觉得用一个映射(map)来解决这个问题会更好。
我们可以把(用户ID,网络ID)作为键,把(开始状态,开始时间)作为值,像下面这样定义:
class UserNet:
user_id = -1
net_id = -1
// Other Operation
class StartStatus:
start_flag = False
start_time = -1
// Other Operation
当你读取一行数据时,首先判断这一行的状态字符串是“开始”(START)还是“结束”(END)。
如果是“结束”,那么就从这一行开始读取,去新的映射结构中查找,找到开始时间,然后进行减法运算来得到你的答案。
如果是“开始”,那么就把这个值插入到新的映射结构中。
如果你不想进行错误判断,start_flag就不是必需的。它是用来表示同一个用户的重复开始状态的,可能你并不需要这个。
4
你代码里唯一的问题是,当遇到第一个START时,你就开始查找END关键字,而不是从文件的开头开始查找。其实应该从文件的第一行开始查找。
同时,我们还需要考虑到同一行不能被重复查找。为此,我们可以使用一个列表,来记录已经查找过的行号。
我没有写新的代码,而是对你的代码进行了修改。
>>> l=[] ## empty list
>>> csv_file=open('dates.csv')
>>> csv_read = csv.reader(csv_file)
>>> for row in csv_read:
if row[0].split()[4]=="start":
n1=datetime.datetime.strptime(row[0].split()[2], '%H:%M:%S')
s=csv_read.line_num
csv_file1=open('/Python34/Workspace/Stoverflow/dates.csv')
csv_read1 = csv.reader(csv_file1)
for row2 in csv_read1:
e=csv_read1.line_num
## Inside if iam adding to more checks that verify that the same line is not traversed again and the END flag is always encountered after START flag
if (row2[0].split()[4]=="End" and row[0].split()[6]==row2[0].split()[6] and row[0].split()[5]==row2[0].split()[5] and (csv_read1.line_num not in l) and s<csv_read1.line_num):
n2=datetime.datetime.strptime(row2[0].split()[2], '%H:%M:%S')
print("Connect : ",row[0].split()[2]," Disconnect :",row2[0].split()[2])
diff = n2 - n1
print("time difference = ", diff.seconds,"\n")
l.append(csv_read1.line_num)
del csv_read1
break
del csv_file1