<p>您可以添加一个helper列来计算每行上日期范围<code>d</code>和日期范围<code>Start</code>和<code>End</code>之间的重叠天数。然后,在这些重叠的日子对行进行筛选>;0最后,计算筛选行上不同的<code>Category</code>数:</p>
<ol>
<li>将日期转换为日期时间格式(如果尚未使用日期时间格式):</li>
</ol>
<pre><code>df['Start'] = pd.to_datetime(df['Start'])
df['End'] = pd.to_datetime(df['End'])
</code></pre>
<ol start=“2”>
<li>在每一行上,通过<code>pd.date_range()</code>创建<code>Start</code>和<code>End</code>日期之间的日期范围。然后,通过numpy函数<a href="https://numpy.org/doc/stable/reference/generated/numpy.intersect1d.html" rel="nofollow noreferrer">^{<cd9>}</a>获得日期范围<code>d</code>的重叠日期范围(以获得两个日期范围之间的交集)。通过获取交叉点的长度来获取重叠天数</李>
</ol>
<pre><code>df['overlap_days'] = df.apply(lambda x: len(np.intersect1d(pd.date_range(start=x['Start'], end=x['End'], freq='D'), d)), axis=1)
</code></pre>
<p>结果:</p>
<pre><code>print(df)
Category Start End overlap_days
0 a 2014-12-01 2015-06-01 152
1 a 2015-10-02 2015-10-16 15
2 b 2015-10-01 2016-04-01 92
3 b 2015-10-01 2015-12-01 62
4 c 2015-06-01 2015-08-01 62
</code></pre>
<ol start=“3”>
<li>对日期重叠的行进行筛选>;按<code>.loc</code>计算0,并按<a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.nunique.html" rel="nofollow noreferrer">^{<cd12>}</a>计算筛选行上不同的<code>Category</code>数,如下所示:</li>
</ol>
<pre><code>df.loc[df['overlap_days'] > 0, 'Category'].nunique()
</code></pre>
<p><strong>输出:</strong></p>
<pre><code>3
</code></pre>
<p><strong>性能考虑因素</strong></p>
<p>此解决方案在引擎盖下使用快速矢量化Numpy操作。尽管它使用<code>apply()</code>循环,但与使用Python循环和/或列表理解的逻辑相比,它仍然运行得更快</p>
<p>基准测试表明,该解决方案的运行速度为2.57ms,而其他解决方案的运行速度为41.7ms、142ms和288ms</p>