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中的段的值分配一个值
例如:
dataframe1100 200
中的第一段包含在dataframe20 400
的第一段中,然后我应该分配值0
dataframe1300 450
中的第二段包含在dataframe2的第一段0 400
和第二段401 499
中。在这种情况下,我需要将该段拆分为2,并指定2个相应的值。ie300400->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中不允许使用空间隔对象您知道如何处理这种情况吗?