Python 数据帧中两列的交点

Python 数据帧中两列的交点,python,pandas,dataframe,Python,Pandas,Dataframe,我有两个数据帧:dataframe1和dataframe2,看起来像这样: mydataframe1 Out[15]: Start End 100 200 300 450 500 700 mydataframe2 Out[16]: Start End Value 0 400 0 401 499 -1 500 1000

我有两个数据帧:
dataframe1
dataframe2
,看起来像这样:

mydataframe1
Out[15]: 
    Start   End  
    100     200
    300     450
    500     700


mydataframe2
Out[16]:
  Start   End       Value     
  0       400       0  
  401     499       -1  
  500     1000      1  
  1001    1698      1  
每行对应一个段(起点和终点)。 对于dataframe1中的每个段,我希望根据分配给dataframe2中的段的值分配一个值

例如:

dataframe1
100 200
中的第一段包含在dataframe2
0 400
的第一段中,然后我应该分配值0

dataframe1
300 450
中的第二段包含在dataframe2的第一段
0 400
和第二段
401 499
中。在这种情况下,我需要将该段拆分为2,并指定2个相应的值。ie
300400->value 0
401-450 value->-1

最终的dataframe1应该如下所示

mydataframe1
Out[15]: 
    Start   End  Value
    100     200  0
    300     400  0
    401     450  -1
    500     700  1

我希望我是克莱尔。你能帮我吗?

我怀疑是否有一种方法可以直接解决这个问题。 您必须手动计算交点,才能得到所需的结果。该库至少使间隔重叠计算更简单、更高效

IntervalTree.search()
返回与提供的间隔重叠的(完整)间隔,但不计算它们的交点。这就是为什么我还要应用我定义的
intersect()
函数

import pandas as pd
from intervaltree import Interval, IntervalTree

def intersect(a, b):
    """Intersection of two intervals."""
    intersection = max(a[0], b[0]), min(a[1], b[1])
    if intersection[0] > intersection[1]:
        return None
    return intersection

def interval_df_intersection(df1, df2):
    """Calculate the intersection of two sets of intervals stored in DataFrames.
    The intervals are defined by the "Start" and "End" columns.
    The data in the rest of the columns of df1 is included with the resulting
    intervals."""
    tree = IntervalTree.from_tuples(zip(
            df1.Start.values,
            df1.End.values,
            df1.drop(["Start", "End"], axis=1).values.tolist()
        ))

    intersections = []
    for row in df2.itertuples():
        i1 = Interval(row.Start, row.End)
        intersections += [list(intersect(i1, i2)) + i2.data for i2 in tree[i1]]

    # Make sure the column names are in the correct order
    data_cols = list(df1.columns)
    data_cols.remove("Start")
    data_cols.remove("End")
    return pd.DataFrame(intersections, columns=["Start", "End"] + data_cols)

interval_df_intersection(mydataframe2, mydataframe1)

结果与您的要求相同。

以下是使用库的答案。它不进行拆分,而是回答标题中的问题,而且速度非常快

设置:

from ncls import NCLS

contents = """Start   End
100     200
300     450
500     700"""

import pandas as pd
from io import StringIO
df = pd.read_table(StringIO(contents), sep="\s+")

contents2 = """Start   End       Value
0       400       0
401     499       -1
500     1000      1
1001    1698      1"""
df2 = pd.read_table(StringIO(contents2), sep="\s+")
执行:

n = NCLS(df.Start.values, df.End.values, df.index.values)

x, x2 = n.all_overlaps_both(df2.Start.values, df2.End.values, df2.index.values)

dfx = df.loc[x]
# Start  End
# 0    100  200
# 0    100  200
# 1    300  450
# 2    500  700

df2x = df2.loc[x2]
# Start   End  Value
# 0      0   400      0
# 1    401   499     -1
# 1    401   499     -1
# 2    500  1000      1

dfx.insert(dfx.shape[1], "Value", df2x.Value.values)
# Start  End  Value
# 0    100  200      0
# 0    100  200      0
# 1    300  450     -1
# 2    500  700      1

“dataframe1 300 350中的第二段包含在dataframe2的前0 400段和第二401 499段中”。。。401到499中如何包含300到350?对不起。。。输入错误如果df1行是df2行的子集,则可以使用apply:df1.apply(lambda x:df2.Value[(df2['Start']=x['End']),axis=1)。然而,您的问题更复杂,我担心您需要循环并考虑所有情况…树中i2的交叉点+=[(*intersect(i1,i2),i2.data)[i1]]给出无效的语法。您似乎在使用Python 2,它不为列表等解包参数。您可以用
交叉点+=[list(intersect(i1,i2))+[i2.data]对于树中的i2[i1]]
非常感谢您的回答…它似乎工作正常。但是,如果mydataframe2在包含字符串的“值”旁边有另一列,代码会给出错误…是否可能具有与“值”列相同的行为?ie将这些信息也添加到MyDataFrame1中,这是一个好主意,可以使其更通用。我相应地更新了代码,使其更整洁。嗨,Martin,如果df1在“开始”和“结束”中包含具有相同值的元素intervalTree给了我一个错误…intervalTree:intervalTree中不允许使用空间隔对象您知道如何处理这种情况吗?