使用Numpy按组计算百分位等级
我是Python新手,我想按组计算百分位排名。我的团队是野生动物管理单位WMU-string,排名基于预测的驼鹿密度PMDEN3-FLOAT值。秩值进入RankMD字段 我的方法是使用for循环来计算每个WMU中的3个列组,但结果是为整个dbf文件创建了3个列组,大约23000条记录,而不考虑WMU。非常感谢您的帮助使用Numpy按组计算百分位等级,numpy,arcpy,percentile,Numpy,Arcpy,Percentile,我是Python新手,我想按组计算百分位排名。我的团队是野生动物管理单位WMU-string,排名基于预测的驼鹿密度PMDEN3-FLOAT值。秩值进入RankMD字段 我的方法是使用for循环来计算每个WMU中的3个列组,但结果是为整个dbf文件创建了3个列组,大约23000条记录,而不考虑WMU。非常感谢您的帮助 import arcpy import numpy as np input = r'K:\Moose\KrigStratPython\TestRank3.dbf' arr =
import arcpy
import numpy as np
input = r'K:\Moose\KrigStratPython\TestRank3.dbf'
arr = arcpy.da.TableToNumPyArray(input, ('PMDEN3', 'Wmu'))
c_arr = [float(x[0]) for x in np.ndarray.flatten(arr)]
for Wmu in arr:
##to create 3 rank for example
p1 = np.percentile(c_arr, 33) # rank = 0
p2 = np.percentile(c_arr, 67) # rank = 1
p3 = np.percentile(c_arr, 100) # rank = 2
#use cursor to update the new rank field
with arcpy.da.UpdateCursor(input , ['PMDEN3','RankMD']) as cursor:
for row in cursor:
if row[0] < p1:
row[1] = 0 #rank 0
elif p1 <= row[0] and row[0] < p2:
row[1] = 1
else:
row[1] = 2
cursor.updateRow(row)
for循环是正确的,但是,UpdateCursor正在迭代表中的所有行。要获得所需的结果,您需要选择表的子集,然后在该子集上使用更新光标。可以通过将查询传递给的where_子句参数来实现这一点 因此,您将得到如下查询:
current_wmu = WMU['wmu'] # This should be the value of the wmu that the for loop is currently on I think it would be WMU['wmu'] but i'm not positive
where_clause = "WMU = '{}'".format(current_wmu) # format the above variable into a query string
然后,您的更新程序将是:
使用arcpy.da.UpdateCursorinput、['PMDEN3','RankMD',其中_子句作为游标:根据BigGerman的建议,我修改了代码,现在可以使用了。脚本循环遍历每个WMU值,并基于PMDEN计算每个组内的排名百分比。为了改进脚本,我应该从输入文件创建一个WMU值数组,而不是手动创建数组
import arcpy
import numpy as np
#fields to be calculated
fldPMDEN = "PMDEN"
fldRankWMU = "RankWMU"
input = r'K:\Moose\KrigStratPython\TestRank3.dbf'
arcpy.MakeFeatureLayer_management(input, "stratLayerShpNoNullsLyr")
WMUs = ["10", "11A", "11B", "11Q", "12A"]
for current_wmu in WMUs:
##to create 3 rank for example
where_clause = "Wmu = '{}'".format(current_wmu) # format the above variable into a query
with arcpy.da.UpdateCursor("stratLayerShpNoNullsLyr", [fldPMDEN,fldRankWMU], where_clause) as cursor:
arr1 = arcpy.da.TableToNumPyArray("stratLayerShpNoNullsLyr", [fldPMDEN,fldRankWMU], where_clause)
c_arrS = [float(x[0]) for x in np.ndarray.flatten(arr1)]
p1 = np.percentile(c_arrS, 33) # rank = 3
p2 = np.percentile(c_arrS, 67) # rank = 2
p3 = np.percentile(c_arrS, 100) # rank = 1 (highest density)
for row in cursor:
if row[0] < p1:
row[1] = 3 #rank 0
elif p1 <= row[0] and row[0] < p2:
row[1] = 2
else:
row[1] = 1
cursor.updateRow(row)
您的解决方案非常有用,where_子句工作正常。但是对于numpy.percentile方法,我需要传递一个仅包含PMDEN3值的一维数组。我如何从UpdateCursor获取这个数组?@Rob我不确定我是否了解你。你不是把c_arr传递到numpy.percentile方法中吗?该数组不只是包含PMDEN3值吗?UpdateCursor可以访问该变量,但我不确定您需要它做什么?我首先读取了一个包含两个值的数组是的,我使用c_arr传递PMDEN3值。您在哪一行遇到问题?在我修订的代码中,我首先读取了一个包含PMDEN3和Wmu值arr1的数组,然后我手动创建一个具有Wmu值的数组,例如Wmu=[10,12A,…]。我在WMUs:中使用for current\u wmu循环执行此操作,使用where\u子句选择记录。此时,我将数组c_arr展平以仅保留PMDEN3值,并将该数组传递给np.percentile。一切正常,但最好不要手动创建WMUs阵列。这是我在这个网站上的第一篇帖子。不知道我是否应该将修改后的代码作为新答案发布?Rob,表中的每条记录都有一个WMU值,对吗?如果将所有WMU值提取为列表,则可以将其转换为集合。在Python中,集合是一个无序集合,不能包含重复项,因此这将消除任何重复项;给你们一个WMU的不同值的区间。例如,如果WMU列表=[10,10,11A,11A,11B,11B,11Q,12A],那么setWMUs将返回集合['10','12A','11A','11Q','11B'],然后您可以在For循环中使用该集合。@BigGerman,您的解决方案应该可以工作,但我仍然获得所有重复的记录。我尝试输入=r'K:\TestRank3.dbf',arr=arcpy.da.tabletonumpyarray输入'Wmu',然后Wmu\u List=setarr,然后打印Wmu\u列表。我得到了完整的重复列表因为arr是一个NumPyArray而不是一个列表,我不确定set是否以同样的方式工作。看起来NumPy数组实际上有一个返回唯一值数组的方法:@bigderman,我尝试了np.uniquearr,它返回了一个唯一的数组yay!,但是print语句生成了[u'10',u'11A',u'11B',…],它的格式与我的WMU列表[10,11A,11B,…]不同。这导致了错误,然后我使用'WMU_unique.astype'str'将数组转换为str格式,结果成功了!问题解决了。