Python 基于另一个字段从字段中提取子字符串的循环优化
我正在处理大型数据集(400万乘4)。第一列是名称标识符,许多行具有相同的名称。第二列是一个位置,从-6开始一直向上,直到遇到一个新的标识符,然后再次开始计数。第三列是一个随机数,在这里不重要。第四列是一个长长的数字序列,就像一个长长的条形码。数据看起来有点像这样:Python 基于另一个字段从字段中提取子字符串的循环优化,python,performance,optimization,pandas,Python,Performance,Optimization,Pandas,我正在处理大型数据集(400万乘4)。第一列是名称标识符,许多行具有相同的名称。第二列是一个位置,从-6开始一直向上,直到遇到一个新的标识符,然后再次开始计数。第三列是一个随机数,在这里不重要。第四列是一个长长的数字序列,就像一个长长的条形码。数据看起来有点像这样: YKLOI -6 01 123456789012345678901234 YKLOI -5 25 123456789012345678901234 YKLOI -4 05 123
YKLOI -6 01 123456789012345678901234
YKLOI -5 25 123456789012345678901234
YKLOI -4 05 123456789012345678901234
YKLOI -3 75 123456789012345678901234
YKLOI -2 83 123456789012345678901234
YKLOI -1 05 123456789012345678901234
YKLOI 0 34 123456789012345678901234
YKLOI 1 28 123456789012345678901234
YKLJW -6 87 569845874254658425485
YKLJW -5 87 569845874254658425485
...
YKLOI -6 01 123 #puts 1st triplet in position -6
YKLOI -5 25 456 #puts 2nd triplet in position -5
YKLOI -4 05 789 #puts 3rd triplet in position -4
YKLOI -3 75 012 #puts 4th triplet in position -3
YKLOI -2 83 345 ...
YKLOI -1 05 678
YKLOI 0 34 901
YKLOI 1 28 234 #puts last triplet in the last position
YKLJW -6 87 569 #puts 1st triplet in position -6
YKLJW -5 87 845 #puts 2nd triplet in position -5
...
我想让它看起来像这样:
YKLOI -6 01 123456789012345678901234
YKLOI -5 25 123456789012345678901234
YKLOI -4 05 123456789012345678901234
YKLOI -3 75 123456789012345678901234
YKLOI -2 83 123456789012345678901234
YKLOI -1 05 123456789012345678901234
YKLOI 0 34 123456789012345678901234
YKLOI 1 28 123456789012345678901234
YKLJW -6 87 569845874254658425485
YKLJW -5 87 569845874254658425485
...
YKLOI -6 01 123 #puts 1st triplet in position -6
YKLOI -5 25 456 #puts 2nd triplet in position -5
YKLOI -4 05 789 #puts 3rd triplet in position -4
YKLOI -3 75 012 #puts 4th triplet in position -3
YKLOI -2 83 345 ...
YKLOI -1 05 678
YKLOI 0 34 901
YKLOI 1 28 234 #puts last triplet in the last position
YKLJW -6 87 569 #puts 1st triplet in position -6
YKLJW -5 87 845 #puts 2nd triplet in position -5
...
第四列的长度变化很大,但第二列的数字总是按顺序排列的
下面的代码是我得到的一个,它实际上正在做这项工作,但它需要花很长时间才能完成。到目前为止,它已经运行了将近18个小时,仅仅超过100万条生产线
我尝试了一些替代方法,例如仅当连续行中第一列中的名称不同时才构建一个映射,但这只是在其中添加了一条语句,并使代码速度慢得多
是否有人对如何提高此任务的性能提出建议
import pandas as pd
#imports data
d = pd.read_csv('INPUT_FILE', sep='\t')
#acknowledges that data was imported
print "Import Okay"
#sets output path
output='OUTPUT_FILE'
#loops from the first row till the end
for z in xrange(0,len(d)-1):
#goes to the fourth column, split the content every 3 characters and creates
#a list of these triplets.
mop=map(''.join, zip(*[iter(d.loc[z][3])]*3))
#substitutes the content of the fourth column in the z line by the triplet in
#the z+6 positon
d.ix[z,3] = mop[int(d.loc[z][1])+6]
#writes the new z line into the output file
d.loc[[z]].to_csv(output, sep='\t', header=False, index=False, mode='a')
#acknowledges that the code is through
print "Done"
两个简单的变化开始。第一,不要递增地写入输出文件,它会增加很多不必要的开销,这是迄今为止您最大的问题 第二,你似乎经历了很多步骤来拉出三胞胎。这样做效率更高,
.apply
删除了一些循环开销
def triplet(row):
loc = (row[1] + 6) * 3
return row[3][loc:loc+3]
d[3] = d.apply(triplet, axis=1)
# save the whole file once
d.to_csv(output2, sep='\t', header=False, index=False)
也许让程序更高效的唯一方法就是用更高效的编程语言重写它。你将获得10倍到100倍或更多的速度。众所周知,Python不是一种特别有效的语言,循环效率非常低。最后一列中的数据是字符串还是长整数?@Renzo-因此,一旦编写了Python程序,除了用另一种语言重写它之外,没有其他方法可以使它更快了?您的Python IDE是一块石碑吗?@Renzo-众所周知,许多人不了解如何有效地使用Python。@Alexander,许多人在优化Python代码方面存在问题是完全正确的,并且通常有很大的空间来改进任何语言中的任何程序。但我认为,许多人在某项工作中使用了错误的工具,这也是事实。如果OP说“这是永远的”,那么在我看来只有两件事可以真正改善这种情况:要么从根本上改变算法,降低其复杂性,要么改变语言,使用机器代码编译的语言。如果给出的答案降低了复杂性,问题就解决了。否则……事实上,持续的储蓄是一种拖累。只是这已经有所帮助,现在我每个循环只需要3秒,而不是15秒。但是这个函数在某种程度上不起作用——要么我做错了什么(很可能!),要么它实际上将循环周期增加到了8秒。关于我可能做错了什么有什么想法吗?你能发布你的代码,它不工作或者你得到的错误吗?请记住,
.apply
是矢量化的,它不应该在循环中使用,只使用一次。您应该会看到另一个显著的加速效果(根据数据的大小,我得到了20-100倍的加速)。我现在刚刚重新编辑了它,不知怎么的,它运行得太快了,以至于我一开始没有看到结果-这会添加一个新列,而不是替换它,并且考虑到数据的大小,很容易在其中丢失。但它就像一个符咒!所有数据在1分钟内处理完毕。我对它的速度感到震惊。谢谢。