<p>问题是,我相信,你的数据有5300个不同的组。因此,在你的功能中任何慢的东西都会被放大。可能可以使用矢量化操作而不是函数中的<code>for</code>循环来节省时间,但省去几秒钟的一个更简单的方法是<code>return 0</code>,而不是<code>return group</code>。当您<code>return group</code>时,pandas将实际创建一个新的数据对象,该对象将组合排序后的组,而您似乎不使用这些组。当您<code>return 0</code>时,pandas将组合5300个零,这要快得多。</p>
<p>例如:</p>
<pre><code>cols = ['ID_number','TimeOfDay','TypeOfCargo','TrackStart']
groups = df.groupby(cols)
print(len(groups))
# 5353
%timeit df.groupby(cols).apply(lambda group: group)
# 1 loops, best of 3: 2.41 s per loop
%timeit df.groupby(cols).apply(lambda group: 0)
# 10 loops, best of 3: 64.3 ms per loop
</code></pre>
<p>只需将不使用的结果合并起来大约需要2.4秒;剩下的时间是循环中的实际计算,您应该尝试将其矢量化。</p>
<hr/>
<p>编辑:</p>
<p>通过在<code>for</code>循环之前进行快速的向量化检查并返回<code>0</code>,而不是<code>group</code>,我将时间减少到大约~2sec,这基本上是对每个组进行排序的成本。尝试此功能:</p>
<pre><code>def Full_coverage(group):
if len(group) > 1:
group = group.sort('SectionStart', ascending=True)
# this condition is sufficient to find when the loop
# will add to the list
if np.any(group.values[1:, 4] != group.values[:-1, 5]):
start_km = group.iloc[0,4]
end_km = group.iloc[0,5]
end_km_index = group.index[0]
for index, (i, j) in group.iloc[1:,[4,5]].iterrows():
if i != end_km:
incomplete_coverage.append(('Expected startpoint: '+str(end_km)+' (row '+str(end_km_index)+')', \
'Found startpoint: '+str(i)+' (row '+str(index)+')'))
start_km = i
end_km = j
end_km_index = index
return 0
cols = ['ID_number','TimeOfDay','TypeOfCargo','TrackStart']
%timeit df.groupby(cols).apply(Full_coverage)
# 1 loops, best of 3: 1.74 s per loop
</code></pre>
<hr/>
<p>编辑2:这里有一个例子,其中包含了我的建议,将排序移到groupby之外,并删除不必要的循环。对于给定的示例,删除循环的速度不会快得多,但如果有许多不完整项,则速度会更快:</p>
<pre><code>def Full_coverage_new(group):
if len(group) > 1:
mask = group.values[1:, 4] != group.values[:-1, 5]
if np.any(mask):
err = ('Expected startpoint: {0} (row {1}) '
'Found startpoint: {2} (row {3})')
incomplete_coverage.extend([err.format(group.iloc[i, 5],
group.index[i],
group.iloc[i + 1, 4],
group.index[i + 1])
for i in np.where(mask)[0]])
return 0
incomplete_coverage = []
cols = ['ID_number','TimeOfDay','TypeOfCargo','TrackStart']
df_s = df.sort_values(['SectionStart','SectionStop'])
df_s.groupby(cols).apply(Full_coverage_nosort)
</code></pre>