不确定这是否是最佳方法,但您可以使用reindex
、join
、groupby
和agg
来获取您的间隔,例如:
使用reindex()
将每个df
扩展,以便索引为范围的每个值(从Start
到Stop
),并使用pad
填充值:
In []:
df_a_expanded = df_a.set_index('Start').reindex(range(max(df_a['Stop'])+1)).fillna(method='pad')
df_a_expanded
Out[]:
Stop Value
Start
0 100.0 0.0
1 100.0 0.0
2 100.0 0.0
3 100.0 0.0
4 100.0 0.0
...
997 1000.0 0.0
998 1000.0 0.0
999 1000.0 0.0
1000 1000.0 0.0
[1001 rows x 2 columns]
In []:
df_b_expanded = df_b.set_index('Start').reindex(range(max(df_b['Stop'])+1)).fillna(method='pad')
将两个扩展的 dfs
连接起来:
In []:
df = df_a_expanded.join(df_b_expanded, lsuffix='_dfA', rsuffix='_dfB').reset_index()
df
Out[]:
Start Stop_dfA Value_dfA Stop_dfB Value_dfB
0 0 100.0 0.0 50.0 0.0
1 1 100.0 0.0 50.0 0.0
2 2 100.0 0.0 50.0 0.0
3 3 100.0 0.0 50.0 0.0
4 4 100.0 0.0 50.0 0.0
...
注意:您可以忽略“Stop”列,也可以在上一步中删除它们。
没有标准的方法可以仅按连续值(类似于itertools.groupby)进行分组,因此需要使用cumsum()技巧:
In []:
groups = (df[['Value_dfA', 'Value_dfB']] != df[['Value_dfA', 'Value_dfB']].shift()).any(axis=1).cumsum()
g = df.groupby([groups, 'Value_dfA', 'Value_dfB'], as_index=False)
现在您可以通过使用min
,max
聚合组来获得所需的结果:
In []:
df_out = g['Start'].agg({'Start': 'min', 'Stop': 'max'})
df_out
Out[]:
Value_dfA Value_dfB Start Stop
0 0.0 0.0 0 50
1 0.0 1.0 51 100
2 1.0 1.0 101 200
3 0.0 1.0 201 300
4 0.0 0.0 301 1000
现在您只需要添加
SameValue
列,如果需要,可以对列进行排序,以获得所需的精确输出:
In []:
df_out['SameValue'] = (df_out['Value_dfA'] == df_out['Value_dfB'])*1
df_out[['Start', 'Stop', 'SameValue', 'Value_dfA', 'Value_dfB']]
Out[]:
Start Stop SameValue Value_dfA Value_dfB
0 0 50 1 0.0 0.0
1 51 100 0 0.0 1.0
2 101 200 1 1.0 1.0
3 201 300 0 0.0 1.0
4 301 1000 1 0.0 0.0
这假设两个数据框的范围相同,否则您需要处理使用
join()
时会得到的
NaN
。
df_a
和df_b
,前一个区间的上限难道不仅是100
吗? - AChampionpandas.merge_asof
对于这个问题会有所帮助?(https://pandas.pydata.org/pandas-docs/stable/generated/pandas.merge_asof.html)。 - Guybrush