使用threshold-python对点是否在指定区域内进行分类

使用threshold-python对点是否在指定区域内进行分类,python,pandas,classification,Python,Pandas,Classification,我有一个包含xy点的df。如果这些点仅位于这些帧的多边形内,我想删除这些点。下面的区域展示了这一点。这些点会从这个区域来来去去去,所以我只想在它们被确定放置在那里时移除它们。否则,将它们保留在df中 中心的困境是我不想在这里通过一个严格的规则。因为这些点是流动的,我希望结合灵活性。例如,某些点可能暂时通过该区域,不应移除。而其他点位于该区域内的时间足够长,因此应将其移除 最明显的方法是在这里传递某种阈值方法。使用下面的df1,A位于3帧的区域内,而B位于7帧的区域内。如果我通过了>5帧的阈值,则

我有一个包含xy点的df。如果这些点仅位于这些帧的多边形内,我想删除这些点。下面的区域展示了这一点。这些点会从这个区域来来去去去,所以我只想在它们被确定放置在那里时移除它们。否则,将它们保留在df中

中心的困境是我不想在这里通过一个严格的规则。因为这些点是流动的,我希望结合灵活性。例如,某些点可能暂时通过该区域,不应移除。而其他点位于该区域内的时间足够长,因此应将其移除

最明显的方法是在这里传递某种阈值方法。使用下面的df1,A位于3帧的区域内,而B位于7帧的区域内。如果我通过了>5帧的阈值,则该区域内的帧应移除B,而a不应受到影响

问题是,它必须是连续的帧。点会来来去去去,所以我只想在连续5帧后移除

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import random

df = pd.DataFrame({
    'X' : [-5,10,-5,-5,-5,-5,-5,-5,-5,30,20,10,0,-5,-5,-5,-5,-5,-5,-5,5],  
    'Y' : [50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50],                  
    'Label' : ['A','A','A','A','A','A','A','A','A','A','B','B','B','B','B','B','B','B','B','B','B'], 
    'Time' : [501,502,503,504,505,506,507,508,509,510,501,502,503,504,505,506,507,508,509,510,511],                         
    })

# designated area
x = ([1.5,-0.5,-1.25,-0.5,1.5,-11,-11,1.5]) 
y = ([75,62.5,50,37.5,25,25,75,75])

area = mpltPath.Path([[x, y] for x, y in zip(x, y)])
df1['is_inside'] = area.contains_points(df1[['X','Y']])
输出:

预期产出:

     X   Y Label  Time 
0   -5  50     A   501     
1   10  50     A   502         
9   30  50     A   510     
10  20  50     B   501     
11  10  50     B   502     
12   0  50     B   503     
20   5  50     B   511     

我首先复制您的数据:

作为pd进口熊猫 将matplotlib导入为mpl x=[1.5,-0.5,-1.25,-0.5,1.5,-11,1.5] y=[75,62.5,50,37.5,25,25,75,75] 顶点=列表Zipx,y 多边形=mpl.path.Pathvertices,闭合=真 df=pd.DataFrame{ “X”:[-5,10,-5,-5,-5,-5,-5,-5,30, 20, 10, 0, -5, -5, -5, -5, -5, -5, -5, 5], Y:[50,50,50,50,50,50,50,50,50,50,50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50], “标签”:列出“A”*10+B”*11, “时间”:2*ListRange501511+[511] } df=df.sort_值['Label','Time'] df['is_inside']=多边形。包含_点df[['X','Y']] 这是原始数据帧的外观:

In[91]:df 出[91]: X Y标签时间在\u内 0-5 50 A 501正确 11050A502假 2-5 50 A 503正确 3-5 50 A 504正确 4-5 50 A 505正确 5-5 50 A 506正确 6-5 50 A 507正确 7-5 50 A 508正确 8-5 50 A 509正确 93050A 510假 102050B501错误 111050B502错误 12050b503假 13-5 50 B 504正确 14-5 50 B 505正确 15-5 50 B 506正确 16-5 50 B 507正确 17-5 50 B 508正确 18-5 50 B 509正确 19-5 50 B 510正确 205050B511错误 可以使用删除不需要的点:

将numpy作为np导入 从itertools导入groupby 阈值=5 索引器=[] 对于np.uniquedf['label']中的标签: 对于键,groupbydf.loc[df['Label']==Label]['is_in']中的组: runlength=lenlistgroup 移除=密钥和运行长度>阈值 index.extend[remove]*runlength df.dropdf[indexer].index,inplace=True 输出:

In[92]:df 出[92]: X Y标签时间在\u内 0-5 50 A 501正确 11050A502假 93050A 510假 102050B501错误 111050B502错误 12050b503假 205050B511错误
我首先复制您的数据:

作为pd进口熊猫 将matplotlib导入为mpl x=[1.5,-0.5,-1.25,-0.5,1.5,-11,1.5] y=[75,62.5,50,37.5,25,25,75,75] 顶点=列表Zipx,y 多边形=mpl.path.Pathvertices,闭合=真 df=pd.DataFrame{ “X”:[-5,10,-5,-5,-5,-5,-5,-5,30, 20, 10, 0, -5, -5, -5, -5, -5, -5, -5, 5], Y:[50,50,50,50,50,50,50,50,50,50,50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50], “标签”:列出“A”*10+B”*11, “时间”:2*ListRange501511+[511] } df=df.sort_值['Label','Time'] df['is_inside']=多边形。包含_点df[['X','Y']] 这是原始数据帧的外观:

In[91]:df 出[91]: X Y标签时间在\u内 0-5 50 A 501正确 11050A502假 2-5 50 A 503正确 3-5 50 A 504正确 4-5 50 A 505正确 5-5 50 A 506正确 6-5 50 A 507正确 7-5 50 A 508正确 8-5 50 A 509正确 93050A 510假 102050B501错误 111050B502错误 12050b503假 13-5 50 B 504正确 14-5 50 B 505正确 15-5 50 B 506正确 16-5 50 B 507正确 17-5 50 B 508正确 18-5 50 B 509正确 19-5 50 B 510正确 205050B511错误 可以使用删除不需要的点:

将numpy作为np导入 从itertools导入groupby 阈值=5 索引器=[] 标签一 n np.uniquedf['Label']: 对于键,groupbydf.loc[df['Label']==Label]['is_in']中的组: runlength=lenlistgroup 移除=密钥和运行长度>阈值 index.extend[remove]*runlength df.dropdf[indexer].index,inplace=True 输出:

In[92]:df 出[92]: X Y标签时间在\u内 0-5 50 A 501正确 11050A502假 93050A 510假 102050B501错误 111050B502错误 12050b503假 205050B511错误
最干净有效的方法是使用pd.DataFrame.groupby。这还有一个额外的好处,即可以轻松添加更多多边形/过滤器,以实现更复杂的分类

定义对象 使用与原始问题相同的数据

# Define data
df = pd.DataFrame({
    'X': [20, 10, 0, -5, -5, -5, 0, 10, 20, 30, 20, 10, 0, -5, -5, -5, -5, -5, -5, -5],
    'Y': [50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50],
    'Label': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
    'Time': [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510],
})
直接从matplotlib.path.path对象定义多边形,即无需先打印

# Define Polygon
x, y = [1.5, -0.5, -1.25, -0.5, 1.5, -11, -11, 1.5], [75, 62.5, 50, 37.5, 25, 25, 75, 75]
path = mpltPath.Path([[x, y] for x, y in zip(x, y)])
df['is_inside'] = path.contains_points(df[['X','Y']])
滚动分组 排序,因为时间排序对滚动操作很重要

df = df.sort_values(by=['Label','Time'])
df = df.reset_index(drop=True)
下面的函数用于检查每个标签是否在n个连续帧的多边形中

def get_label_to_remove(df, n):
    d = df.groupby(['Label'])['is_inside'].agg(lambda x: x.rolling(n).agg(all).any())
    return d.to_dict()
测试用例 观察值分布如下:1表示多边形内的一个点:

        501 502 503 504 505 506 507 508 509 510
    A   0   0   0   1   1   1   0   0   0   0
    B   0   0   0   1   1   1   1   1   1   1
注意A连续出现3次,B连续出现7次。观察函数在[2,3,4]和[6,7,8]处的行为

这适用于任意数量的标签,无需任何更改

只删除缺点 应OP的要求添加此项。以下内容确定了坏点,而不仅仅是用于移除as掩码的坏标签

快跑

In[0]:
df

Out[0]:
0   20  50  A   501 False   False
1   10  50  A   502 False   False
2   0   50  A   503 False   False
3   -5  50  A   504 True    False
4   -5  50  A   505 True    False
5   -5  50  A   506 True    False
6   0   50  A   507 False   False
7   10  50  A   508 False   False
8   20  50  A   509 False   False
9   30  50  A   510 False   False
10  20  50  B   501 False   False
11  10  50  B   502 False   False
12  0   50  B   503 False   False
13  -5  50  B   504 True    True
14  -5  50  B   505 True    True
15  -5  50  B   506 True    True
16  -5  50  B   507 True    True
17  -5  50  B   508 True    True
18  -5  50  B   509 True    True
19  -5  50  B   510 True    True

最干净有效的方法是使用pd.DataFrame.groupby。这还有一个额外的好处,即可以轻松添加更多多边形/过滤器,以实现更复杂的分类

定义对象 使用与原始问题相同的数据

# Define data
df = pd.DataFrame({
    'X': [20, 10, 0, -5, -5, -5, 0, 10, 20, 30, 20, 10, 0, -5, -5, -5, -5, -5, -5, -5],
    'Y': [50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50],
    'Label': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
    'Time': [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510],
})
直接从matplotlib.path.path对象定义多边形,即无需先打印

# Define Polygon
x, y = [1.5, -0.5, -1.25, -0.5, 1.5, -11, -11, 1.5], [75, 62.5, 50, 37.5, 25, 25, 75, 75]
path = mpltPath.Path([[x, y] for x, y in zip(x, y)])
df['is_inside'] = path.contains_points(df[['X','Y']])
滚动分组 排序,因为时间排序对滚动操作很重要

df = df.sort_values(by=['Label','Time'])
df = df.reset_index(drop=True)
下面的函数用于检查每个标签是否在n个连续帧的多边形中

def get_label_to_remove(df, n):
    d = df.groupby(['Label'])['is_inside'].agg(lambda x: x.rolling(n).agg(all).any())
    return d.to_dict()
测试用例 观察值分布如下:1表示多边形内的一个点:

        501 502 503 504 505 506 507 508 509 510
    A   0   0   0   1   1   1   0   0   0   0
    B   0   0   0   1   1   1   1   1   1   1
注意A连续出现3次,B连续出现7次。观察函数在[2,3,4]和[6,7,8]处的行为

这适用于任意数量的标签,无需任何更改

只删除缺点 应OP的要求添加此项。以下内容确定了坏点,而不仅仅是用于移除as掩码的坏标签

快跑

In[0]:
df

Out[0]:
0   20  50  A   501 False   False
1   10  50  A   502 False   False
2   0   50  A   503 False   False
3   -5  50  A   504 True    False
4   -5  50  A   505 True    False
5   -5  50  A   506 True    False
6   0   50  A   507 False   False
7   10  50  A   508 False   False
8   20  50  A   509 False   False
9   30  50  A   510 False   False
10  20  50  B   501 False   False
11  10  50  B   502 False   False
12  0   50  B   503 False   False
13  -5  50  B   504 True    True
14  -5  50  B   505 True    True
15  -5  50  B   506 True    True
16  -5  50  B   507 True    True
17  -5  50  B   508 True    True
18  -5  50  B   509 True    True
19  -5  50  B   510 True    True
免责声明: 这是上述答案的延伸。我认为以上两个答案都很好,我只想增加2美分,而不是重新发明轮子。所以我要延长Leonardus Chen的回答,所有的荣誉都应该归于他

一个人可能想要扩展前面答案的原因 为了使您的检测对支出者更具鲁棒性,您可以引入某种平滑。最坏情况:5帧中有4帧的位置在多边形内部,但恰好每5帧的位置在单个帧的外部

平滑可以是一个简单的标准,如移除,如果位置在多边形内的连续帧数至少为8帧中的5帧,或者可以更平滑,并使用一些例如高斯加权曲线

代码库 为此,您可以像Leonardus Chen那样:

从Leonardus Chen复制的代码创建了一个完全有效的示例 作为pd进口熊猫 将matplotlib.path导入为mpltPath 定义数据 df=pd.DataFrame{ “X”:[20,10,0,-5,-5,0,10,20,30,20,10,0,-5,-5,-5], ‘Y’:[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50], ‘标签’:[‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘B’、‘B’、‘B’、‘B’、‘B’、‘B’、‘B’], “时间”:[501、502、503、504、505、506、507、508、509、510、501、502、503、504、505、506、507、508、509、510], } 定义多边形 x、 y=[1.5,-0.5,-1.25,-0.5,1.5,-11,-11,1.5],[75,62.5,50,37.5,25,25,75,75] path=mpltPath.path[[x,y]表示x,y在zipx中,y] df['is_inside']=路径。包含_点df[['X','Y']] 代码扩展 方法1 现在您继续使用df['is_inside']

首先,我们将通过将布尔值相加为True=1,False=0来计算得到的True数。 之后,我们将检查数字是否高于设定的5。 确保将min_periods设置为1,否则不会为前7个条目创建滚动窗口,因为窗口的大小尚未达到8。 如果8个帧中有5个帧的内部外观如下所示,请删除:

df['inside_score']=df['is_inside'].滚动窗口=8,最小周期=1.sum df['inside_score_critical']=df['inside_score']>=5 方法2 我将给出一个类似的标准,它使用高斯平滑函数,而不是设置窗口大小。不幸的是,要创建所需的结果,您必须使用num 贝尔斯

在这里,windows参数无关紧要,但通常应该比std=4高得多,否则可能会出现不太平滑的截止。 相反,设置std=4以控制高斯曲线的宽度,以获得所需的跨度。我发现std为4的行为与上述方法相似,但希望更平滑一些 df['inside_score_2']=df['is_inside'].rollingwindow=10,min_periods=1,win_type=gaussian.sumstd=4 df['inside_score_2_critical']=df['inside_score_2']>=5 免责声明: 这是上述答案的延伸。我认为以上两个答案都很好,我只想增加2美分,而不是重新发明轮子。所以我要延长Leonardus Chen的回答,所有的荣誉都应该归于他

一个人可能想要扩展前面答案的原因 为了使您的检测对支出者更具鲁棒性,您可以引入某种平滑。最坏情况:5帧中有4帧的位置在多边形内部,但恰好每5帧的位置在单个帧的外部

平滑可以是一个简单的标准,如移除,如果位置在多边形内的连续帧数至少为8帧中的5帧,或者可以更平滑,并使用一些例如高斯加权曲线

代码库 为此,您可以像Leonardus Chen那样:

从Leonardus Chen复制的代码创建了一个完全有效的示例 作为pd进口熊猫 将matplotlib.path导入为mpltPath 定义数据 df=pd.DataFrame{ “X”:[20,10,0,-5,-5,0,10,20,30,20,10,0,-5,-5,-5], ‘Y’:[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50], ‘标签’:[‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘A’、‘B’、‘B’、‘B’、‘B’、‘B’、‘B’、‘B’], “时间”:[501、502、503、504、505、506、507、508、509、510、501、502、503、504、505、506、507、508、509、510], } 定义多边形 x、 y=[1.5,-0.5,-1.25,-0.5,1.5,-11,-11,1.5],[75,62.5,50,37.5,25,25,75,75] path=mpltPath.path[[x,y]表示x,y在zipx中,y] df['is_inside']=路径。包含_点df[['X','Y']] 代码扩展 方法1 现在您继续使用df['is_inside']

首先,我们将通过将布尔值相加为True=1,False=0来计算得到的True数。 之后,我们将检查数字是否高于设定的5。 确保将min_periods设置为1,否则不会为前7个条目创建滚动窗口,因为窗口的大小尚未达到8。 如果8个帧中有5个帧的内部外观如下所示,请删除:

df['inside_score']=df['is_inside'].滚动窗口=8,最小周期=1.sum df['inside_score_critical']=df['inside_score']>=5 方法2 我将给出一个类似的标准,它使用高斯平滑函数,而不是设置窗口大小。不幸的是,要想创造出理想的结果,你必须利用数字

在这里,windows参数无关紧要,但通常应该比std=4高得多,否则可能会出现不太平滑的截止。 相反,设置std=4以控制高斯曲线的宽度,以获得所需的跨度。我发现std为4的行为与上述方法相似,但希望更平滑一些 df['inside_score_2']=df['is_inside'].rollingwindow=10,min_periods=1,win_type=gaussian.sumstd=4 df['inside_score_2_critical']=df['inside_score_2']>=5

谢谢我只想删除连续5帧。不是全部。我已经编辑了我的答案,所以阈值现在适用于连续时间而不是总时间。谢谢。如果我有很多标签,使用groupby语句应用函数还是删除Label参数会更有效?我不知道。如果您担心效率问题,那么对代码进行基准测试可能是一个好主意。我很高兴。我很高兴最后我能帮你解决这个问题。谢谢。我只想删除连续5帧。不是全部。我已经编辑了我的答案,所以阈值现在适用于连续时间而不是总时间。谢谢。如果我有很多标签,使用groupby语句应用函数还是删除Label参数会更有效?我不知道。如果您担心效率问题,那么对代码进行基准测试可能是一个好主意。我很高兴。我很高兴最后我能帮你解决这个问题。谢谢。我只想删除连续5帧。“不完全是这样。”jonboy答案现在适用于连续帧,并且随着独特标签数量的增加,它应该可以很好地扩展。谢谢。我觉得这是接近我想要的,但不是完全。我已经更新了question@jonboy喜欢吗?谢谢。我只想删除连续5帧。“不完全是这样。”jonboy答案现在适用于连续帧,并且随着独特标签数量的增加,它应该可以很好地扩展。谢谢。我觉得这是接近我想要的,但不是完全。我已经更新了question@jonboy像这样?