![](/img/trans.png)
[英]What's the best way to visualize sequence of events within pandas in Python?
[英]What is the best way to sort a sequence in Python?
我试图根据需要连续发生的某些条件对表进行排序。 表的简化版本:
Number Time
1 23
2 45
3 67
4 23
5 11
6 45
7 123
8 34
...
我需要检查时间是否连续<40次。 就像我需要检查1-5行,然后2-6等...然后打印并保存到文件的第一次和最后一次。 比如,如果第2-6行符合条件,我将需要打印第2号和第6号的时间。检查应在条件满足后停止。 无需检查其他行。 我实现了一个带有两个临时变量的计数器来检查到目前为止连续3个项目。 它工作正常。 但是,如果我想检查连续30次发生的情况,我不能手动创建30个临时变量。 实现这一目标的最佳方法是什么? 我想我只需要某种循环。 谢谢!
这是我的代码的一部分:
reader = csv.reader(open(filename))
counter, temp1, temp2, numrow = 0, 0, 0, 0
for row in reader:
numrow+=1
if numrow <5:
col0, col1, col4, col5, col6, col23, col24, col25 = float(row[0]),
float(row[1]), float(row[4]), float(row[5]),float(row[6]),
float(row[23]), float(row[24]), float(row[25])
if col1 <= 40:
list1=(col1, col3, col4, col5, col6, col23, col24, col25)
counter += 1
if counter == 3:
print("Cell# %s" %filename[-10:-5])
print LAYOUT.format(*headers_short)
print LAYOUT.format(*temp1)
print LAYOUT.format(*temp2)
print LAYOUT.format(*list1)
print ""
elif counter == 1:
temp1=list1
elif counter == 2:
temp2=list1
else:
counter = 0
我实施了Bakuriu建议的解决方案,它似乎正在运作。 但是,结合众多测试的最佳方法是什么? 就像我需要检查几个条件。 让我们说:v
现在我只需打开csv.reader进行每次测试并运行该功能。 我想这不是最有效的方式,虽然它有效。 对不起,我只是一个完整的菜鸟。
csvfiles = glob.glob('processed_data/*.stat')
for filename in csvfiles:
flag=[]
flag.append(filename[-12:-5])
reader = csv.reader(open(filename))
for a, row_group in enumerate(row_grouper(reader,10)):
if all(float(row[1]) < 40 for row in row_group):
str1= "Efficiency is less than 40 in cycles "+ str(a+1)+'-'+str(a+10) #i is the index of the first row in the group.
flag.append(str1)
break #stop processing other rows.
reader = csv.reader(open(filename))
for b, row_group in enumerate(row_grouper(reader,5)):
if all(float(row[3]) < 40 for row in row_group):
str1= "Capacity is less than 40 minutes in cycles "+ str(a+1)+'-'+str(a+5)
flag.append(str1)
break #stop processing other rows.
reader = csv.reader(open(filename))
for b, row_group in enumerate(row_grouper(reader,25)):
if all(float(row[3]) < 40 for row in row_group):
str1= "Time is less than < 40 in cycles "+ str(a+1)+'-'+str(a+25)
flag.append(str1)
break #stop processing other rows.
if len(flag)>1:
for i in flag:
print i
print '\n'
您根本不必对数据进行排序。 一个简单的解决方案可能是
def row_grouper(reader):
iterrows = iter(reader)
current = [next(iterrows) for _ in range(5)]
for next_row in iterrows:
yield current
current.pop(0)
current.append(next_row)
reader = csv.reader(open(filename))
for i, row_group in enumerate(row_grouper(reader)):
if all(float(row[1]) < 40 for row in row_group):
print i, i+5 #i is the index of the first row in the group.
break #stop processing other rows.
row_grouper
函数是一个生成连续行的5个元素列表的生成器。 每次删除组的第一行并在末尾添加新行。
您可以使用deque
而不是普通list
,并使用popleft()
调用替换row_grouper
的pop(0)
,这更有效,尽管如果列表只有5个元素,这并不重要。
或者,您可以使用martineau建议并使用maxlen
关键字参数并避免pop
。 这大约是使用deque的popleft的两倍,这大约是使用list
的pop(0)
两倍。
编辑:要检查多个条件,您可以修改使用多个row_grouper
并使用itertools.tee
来获取迭代的副本。
例如:
import itertools as it
def check_condition(group, row_index, limit, found):
if group is None or found:
return False
return all(float(row[row_index]) < limit for row in group)
f_iter, s_iter, t_iter = it.tee(iter(reader), 3)
groups = row_grouper(f_iter, 10), row_grouper(s_iter, 5), row_grouper(t_iter, 25)
found_first = found_second = found_third = False
for index, (first, second, third) in enumerate(it.izip_longest(*groups)):
if check_condition(first, 1, 40, found_first):
#stuff
found_first = True
if check_condition(second, 3, 40, found_second):
#stuff
found_second = True
if check_condition(third, 3, 40, found_third):
# stuff
found_third = True
if found_first and found_second and found_third:
#stop the code if we matched all the conditions once.
break
第一部分只是导入itertools
(并为其指定一个“别名” it
以避免每次都输入itertools
)。
我已经定义了check_condition
函数,因为条件变得越来越复杂,你不想一遍又一遍地重复它们。 正如您所看到的, check_condition
的最后一行与之前的条件相同:它检查当前“行组”是否验证该属性。 由于我们计划只迭代文件一次,并且当只满足一个条件时我们无法停止循环(因为我们错过了其他条件)我们必须使用一些标志告诉我们条件是否(例如)时间是以前见过或不见过面。 正如您在for
循环中看到的那样,当满足所有条件时,我们会break
循环。
现在,行:
f_iter, s_iter, t_iter = it.tee(iter(reader), 3)
在reader
行上创建一个iterable,并为其创建3个副本。 这意味着循环:
for row in f_iter:
print(row)
将打印文件的所有行,就像for row in reader
执行for row in reader
一样。 但请注意, itertools.tee
允许我们获取行的副本而不必多次读取文件。
之后,我们必须将这些行传递给row_grouper
以验证条件:
groups = row_grouper(f_iter, 10), row_grouper(s_iter, 5), row_grouper(t_iter, 25)
最后,我们必须遍历“行组”。 为了同时执行此操作,我们使用itertools.izip_longest
(在python3中重命名为itertools.zip_longest
(不带i
))。 它就像zip
一样工作,创建成对元素(例如zip([1, 2, 3], ["a", "b", "c"]) -> [(1, "a"), (2, "b"), (3, "c")]
)。 不同的是, izip_longest
垫具有较短iterables None
秒。 这确保我们检查所有可能组的条件(这也是check_condition
必须检查group
是否为None
)。
要获取当前行索引,我们将所有内容包装在enumerate
,就像之前一样。 里面for
代码很简单:您使用检查条件check_condition
,如果条件满足,你做你必须做什么,你必须设置标志条件(因此在下面的循环的条件总是是False
)。
(注意:我必须说我没有测试代码。当我有一点时间时我会测试它,无论如何我希望我给你一些想法。并查看itertools
的文档)。
您不需要对数据进行排序,只需跟踪您要查找的条件是否发生在最后N行数据中。 固定大小的collections.deque
对这类事情很有用。
import csv
from collections import deque
filename = 'table.csv'
GROUP_SIZE = 5
THRESHOLD = 40
cond_deque = deque(maxlen=GROUP_SIZE)
with open(filename) as datafile:
reader = csv.reader(datafile) # assume delimiter=','
reader.next() # skip header row
for linenum, row in enumerate(reader, start=1): # process rows of file
col0, col1, col4, col5, col6, col23, col24, col25 = (
float(row[i]) for i in (0, 1, 4, 5, 6, 23, 24, 25))
cond_deque.append(col1 < THRESHOLD)
if cond_deque.count(True) == GROUP_SIZE:
print 'lines {}-{} had {} consecutive rows with col1 < {}'.format(
linenum-GROUP_SIZE+1, linenum, GROUP_SIZE, THRESHOLD)
break # found, so stop looking
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.