在熊猫中找到间隔的交集

00_*_*_00 7 python merge pandas

我有两个数据帧

df_a=

     Start Stop Value
    0  0     100  0.0
    1  101   200  1.0
    2  201  1000  0.0

df_b=
       Start Stop Value
    0  0     50 0.0
    1  51   300 1.0
    2  301 1000  0.0
Run Code Online (Sandbox Code Playgroud)

我想生成一个DataFrame包含由Startand 标识的区间Stop,其中Value df_a与df_b 相同.对于每一个间隔,我想存储:如果Value是相同的,并且这是在值df_adf_b.期望的输出:

df_out=
  Start Stop SameValue Value_dfA Value_dfB
      0    50    1          0       0
      51   100   0          0       1
      101  200   1          1       1
      201  300   0          0       1
    [...]
Run Code Online (Sandbox Code Playgroud)

ACh*_*ion 2

不确定这是否是最好的方法,但您可以reindex, join, groupbyagg来获取间隔,例如:

\n\n

展开每个值,使索引成为范围 (到)df中的每个值,并使用这些值:StartStopreindex()pad

\n\n
In []:\ndf_a_expanded = df_a.set_index('Start').reindex(range(max(df_a['Stop'])+1)).fillna(method='pad')\ndf_a_expanded\n\nOut[]:\n         Stop  Value\nStart               \n0       100.0    0.0\n1       100.0    0.0\n2       100.0    0.0\n3       100.0    0.0\n4       100.0    0.0\n...\n997    1000.0    0.0\n998    1000.0    0.0\n999    1000.0    0.0\n1000   1000.0    0.0\n\n[1001 rows x 2 columns]\n\nIn []:\ndf_b_expanded = df_b.set_index('Start').reindex(range(max(df_b['Stop'])+1)).fillna(method='pad')\n
Run Code Online (Sandbox Code Playgroud)\n\n

将两个扩展连接起来dfs

\n\n
In []:\ndf = df_a_expanded.join(df_b_expanded, lsuffix='_dfA', rsuffix='_dfB').reset_index()\ndf\n\nOut[]:\n      Start  Stop_dfA  Value_dfA  Stop_dfB  Value_dfB\n0         0     100.0        0.0      50.0        0.0\n1         1     100.0        0.0      50.0        0.0\n2         2     100.0        0.0      50.0        0.0\n3         3     100.0        0.0      50.0        0.0\n4         4     100.0        0.0      50.0        0.0\n...\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意:您可以忽略这些Stop列,也可以在上一步中删除它们。

\n\n

没有标准方法groupby只能处理连续值 (\xc3\xa0 la itertools.groupby),因此求助于cumsum()hack:

\n\n
In []:\ngroups = (df[['Value_dfA', 'Value_dfB']] != df[['Value_dfA', 'Value_dfB']].shift()).any(axis=1).cumsum()\ng = df.groupby([groups, 'Value_dfA', 'Value_dfB'], as_index=False)\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在您可以通过使用,聚合组来获得您想要的结果minmax

\n\n
In []:\ndf_out = g['Start'].agg({'Start': 'min', 'Stop': 'max'})\ndf_out\n\nOut[]:\n   Value_dfA  Value_dfB  Start  Stop\n0        0.0        0.0      0    50\n1        0.0        1.0     51   100\n2        1.0        1.0    101   200\n3        0.0        1.0    201   300\n4        0.0        0.0    301  1000\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在您只需添加SameValue列,如果需要,可以对列进行排序以获得您想要的确切输出:

\n\n
In []:\ndf_out['SameValue'] = (df_out['Value_dfA'] == df_out['Value_dfB'])*1\ndf_out[['Start', 'Stop', 'SameValue', 'Value_dfA', 'Value_dfB']]\n\nOut[]:\n   Start  Stop  SameValue  Value_dfA  Value_dfB\n0      0    50          1        0.0        0.0\n1     51   100          0        0.0        1.0\n2    101   200          1        1.0        1.0\n3    201   300          0        0.0        1.0\n4    301  1000          1        0.0        0.0\n
Run Code Online (Sandbox Code Playgroud)\n\n

这假设两个数据帧的范围相同,或者您将需要处理NaN通过join().

\n