Python中等高线内多多边形面积计算的错误修复方案
多等高线多边形场景下动物家域面积计算报错修复方案
问题背景
我有一个记录动物活动区域所有(X,Y)位置的DataFrame,需要计算研究期间动物占领区域的面积。部分原始数据如下:
X Y 5508.695055 5000.133944 5509.405078 5000.794318 5509.399589 5000.608576 5508.822574 5000.658109 5508.752179 5000.757261 5514.831466 4989.379770 5514.388758 4989.025955 5515.196170 4989.357183 5515.755913 4989.102731 5515.098742 4988.847782
参考建议后,我使用格林定理计算多边形等高线包围面积,并用seaborn的kdeplot绘制等高线多边形,单多边形场景下代码运行正常:
import numpy as np import matplotlib.pylab as plt import seaborn as sns # 用格林定理计算等高线包围的面积 def area(vs): a = 0 x0,y0 = vs[0] for [x1,y1] in vs[1:]: dx = x1-x0 dy = y1-y0 a += 0.5*(y0*dx - x0*dy) x0 = x1 y0 = y1 return a # 绘制核密度估计等高线多边形 fig,ax=plt.subplots() levels = [0.05, 1] # 提前定义levels变量 kde = sns.kdeplot(data=DfHR, x='X', y='Y', shade=True, ax=ax, levels=levels, cmap="Reds", alpha=0.9) # 计算单多边形面积 for i in range(len(levels)): contour = kde.collections[0] vs = contour.get_paths()[0].vertices # 计算顶点包围的面积 a = area(vs) print(f"r = {levels[i]}: a = {np.abs(a)}") plt.show()
但在多多边形场景下修改代码后,出现TypeError: 'int' object is not callable错误,修改后的代码如下:
fig,ax=plt.subplots() kde = sns.kdeplot(data=DfHR, x='X', y='Y', shade=True, ax=ax, levels=[0.05,1], cmap="Reds", alpha=0.9) for i in range(len(levels)): contour = kde.collections[i] vs = contour.get_paths() area = 0 # 这里的变量名覆盖了自定义的area函数 for island in vs: ai = np.abs(area(island.vertices)) # 此时area是整数,无法调用 area += ai print("r = " + str(levels[i]) + ": a =" + str(area)) plt.show()
错误原因
报错的核心原因是变量名冲突:在循环中定义了area = 0,这个变量覆盖了之前自定义的area()函数。当后续执行area(island.vertices)时,Python会把area当成整数变量,而非可调用的函数,因此抛出类型错误。
修复方案
将循环中的面积累加变量重命名,避免与自定义函数名冲突,同时优化代码细节:
import numpy as np import matplotlib.pylab as plt import seaborn as sns # 用格林定理计算等高线包围的面积 def polygon_area(vs): # 也可以直接保留area,只要不重名覆盖即可 a = 0 x0,y0 = vs[0] for x1,y1 in vs[1:]: dx = x1 - x0 dy = y1 - y0 a += 0.5 * (y0 * dx - x0 * dy) x0, y0 = x1, y1 return np.abs(a) # 直接在函数内取绝对值,简化后续代码 # 绘制核密度估计等高线多边形 fig, ax = plt.subplots() levels = [0.05, 1] kde = sns.kdeplot(data=DfHR, x='X', y='Y', shade=True, ax=ax, levels=levels, cmap="Reds", alpha=0.9) # 遍历每个等高线层级,计算多多边形总面积 for idx, level in enumerate(levels): contour = kde.collections[idx] paths = contour.get_paths() total_area = 0 # 重命名累加变量,避免覆盖函数 for path in paths: poly_area = polygon_area(path.vertices) total_area += poly_area print(f"r = {level}: a = {total_area:.2f}") plt.show()
关键修改点
- 变量名冲突解决:将循环中的累加变量从
area改为total_area,或者将自定义函数重命名为polygon_area,避免命名冲突。 - 简化绝对值处理:在自定义面积计算函数内直接取绝对值,避免重复编写
np.abs()。 - 代码可读性优化:使用
enumerate遍历levels,同时获取索引和层级值,代码更简洁。 - 明确变量定义:提前明确定义
levels变量,避免潜在的未定义错误。
内容的提问来源于stack exchange,提问作者kokovado00
相关产品推荐
相关产品推荐

