<h3>案例1:垃圾箱的大小不一</h3>
<p>在这种情况下,我能想到的最好方法是使用<code>pd.cut</code>:</p>
<pre><code>mapper = pd.Series(df_b['Value'])
mapper.index = df_b['StartDateTime']
cutoffs = df_b['StartDateTime'].copy()
cutoffs[cutoffs.index.max() + 1] = df_b['EndDateTime'].max()
bins = pd.cut(df_a['DateTime'], bins=cutoffs)
df_a['Value'] = mapper.loc[pd.IntervalIndex(bins).left].values
</code></pre>
<p>您可以创建一个系列来将开始时间映射到值。然后,您将创建另一个表示截止点的系列,数据帧A中的时间将被放入其中(请注意,您需要手动添加最后一个结束时间)。然后用<code>pd.cut</code>将时间放入那些截止值中,并使用bin的<code>left</code>值来<code>loc</code>映射序列</p>
<h3>案例2:垃圾箱大小相同</h3>
<p>看起来OP的垃圾箱是5分钟的一大块。如果这是正确的,您可以利用<code>pd.Series.dt.floor()</code>将时间从数据帧A快速转换为可以索引数据帧B的时间:</p>
<pre><code>mapper = pd.Series(df_b['Value'])
mapper.index = df_b['StartDateTime']
df_a['Value'] = mapper.loc[df_a['DateTime'].dt.floor('5T')].values
</code></pre>
<h3>定时:</h3>
<p>以下是我使用的示例数据:</p>
<pre><code>import numpy as np
import pandas as pd
size = 100 # tweak this to see each option at scale
dr1 = pd.date_range('01-01-2020 06:00:00', freq='5T', periods=size)
dr2 = pd.date_range('01-01-2020 06:05:00', freq='5T', periods=size)
drA = pd.to_datetime({'year':dr1.year, 'month':dr1.month,
'day':dr1.day, 'hour':dr1.hour,
'minute':np.random.randint(1,60,len(dr1)),
'second':np.random.randint(1,60,len(dr1))}).sort_values()
drA = drA[drA < dr2.max()]
df_a = pd.DataFrame({'DateTime':drA, 'A':range(len(drA))})
df_b = pd.DataFrame({'StartDateTime':dr1, 'EndDateTime':dr2, 'Value':np.random.rand(len(dr2))})
</code></pre>
<p>使用<code>%%timeit</code>和<code>size=100</code>的结果:</p>
<ul>
<li><code>apply</code>:每个循环61毫秒±851微秒(平均±标准偏差为7次,每个循环10次)</li>
<li><code>pd.cut</code>:每个循环8.98 ms±107µs(7次循环的平均值±标准偏差,每个循环100次)</li>
<li><code>dt.floor</code>:每个循环865µs±17.8µs(7次运行的平均值±标准偏差,每个循环1000次)</li>
<li><em>添加@Rik Kraan的答案</em>,每个循环<code>np.where</code>*:1.85 ms±7.8µs(7次循环的平均±标准偏差,每个循环1000次)</li>
</ul>
<p>*这个答案比我的<code>pd.cut</code>好得多,但是当把<code>size</code>增加到<code>1000000</code>时,我也得到了一个<code>MemoryError: Unable to allocate 931. GiB for an array with shape (999999, 1000000) and data type bool</code></p>
<p>因此,发言速度明显快于原始方法。但如果你的垃圾箱不是平均分配的,那就不对了。您可以使用<code>df_b['StartDateTime'].dt.minute.unique()</code>或<code>df_b['StartDateTime'].dt.time.unique()</code>检查这一点。如果可以找到合适的楼层值,甚至可以迭代使用多个楼层值</p>
<p>但是<code>pd.cut</code>版本仍然是一个显著的改进;也许还有一些我没有看到的优化</p>