1

I first classified firstCol into groups and then I want to give the groups with different weighted values in another field, SecondCol. I will need to give different weighted values very often. I find it very time-consuming whenever I modify the weighted values in my script.


My column looks like this:

enter image description here

I use the following script to calculate the SecondCol:

def TextValue(gridcode):
if gridcode <= 5:
    return 1
elif  5 < gridcode <= 15:
    return 2
elif  15 < gridcode <= 30:
    return 3
elif  30 < gridcode <= 40:
    return 4
elif  40 < gridcode <= 55:
    return 5
elif  55 < gridcode <= 100:
    return 6
elif  100 < gridcode :
    return 7
else:
    return "N/A"

TextValue( !firstCol! )

As you can see, I give the weighted value as below:

(weighted values  ,  group).

1   =   group "firstCol  < 5"    
2   =   group "firstCol = 5 - 15"    
3   =   group "firstCol = 15 - 30"    
4   =   group "firstCol = 30 - 40" 
5   =   group "firstCol = 40 - 55"    
6   =   group "firstCol = 55 - 100"    
7   =   group "firstCol > 100"

I wonder if there is a better way to give new weighted values more efficiently. Like, just give a new column in the beginning of the script.

61  =   group "firstCol  < 5"   
8   =   group "firstCol = 5 - 15"    
88  =   group "firstCol = 15 - 30"    
70  =   group "firstCol = 30 - 40"   
52  =   group "firstCol = 40 - 55"    
2   =   group "firstCol = 55 - 100"    
6   =   group "firstCol > 100"

def TextValue( gridcode):
if ...
...
else...

TextValue( !firstCol! )

Then, the script will use the new values, instead of me modifying it in the TextValue.

0

2 Answers 2

4

Try this out:

def Get_Class(depth):
 breaks=[0.5,1,2,3,5,10,100000]
 n=len(breaks)
 for i in range(n):
  if  breaks[i] >= depth:
   m=i+1; break
 return m

'===============================================

Get_Class( !AREA_HA! )

It will look cooler with enumerate though

7
  • Thanks, FelixIP! Your script works for sequence number very well. But what if I need to give non-sequence numbers? like change 1, 2, 3, 4, 5, 6 into 12, 42, 11, 68, 54, 10? Commented Jan 21, 2016 at 3:00
  • 1
    Create second list and pick from it using [m] Commented Jan 21, 2016 at 3:06
  • 1
    Your comment and question are mismatch. One thing reclass using interval (Question) and very different is reclass using lookup (Comment) Commented Jan 21, 2016 at 3:09
  • Sorry for my misleading description. I will edit my question. Commented Jan 21, 2016 at 3:28
  • @ FelixIP Does breaks[i] >= depth: considers the first label(i.e. 5) since then it needs <5? Commented Jan 21, 2016 at 6:49
1

If you need MORE control over the class/label name and interval WISELY and want to use ANY type of equality check then a way is to use dictionary that keeps order (i.e. OrderedDict) and eval check as below where you have good command in interval for class and label for a class.To edit class (i.e. 1,2,3 etc.) and interval (i.e. '0<x<=5','5<x<=15','15<x<=30' etc.) just edit

{1:'0<x<=5',2:'5<x<=15',:'15<x<=30',4:'30<x<=40',5:'40<x<=55',6:'55<x<=100',7:'100<x'}`

See full implementation

from collections import OrderedDict
#Setup class name and interal definition for that class/label- you can change here as you want
lookup_table = OrderedDict({1:'0<x<=5', 2:'5<x<=15', 3:'15<x<=30',4:'30<x<=40',5:'40<x<=55',6:'55<x<=100',7:'100<x'})
#Define function that determines the class/label
def labeller(val):
  try:
    #find the True value for check that is used to determine class/label
    chks = [eval(v.replace('x',str(val))) for v in lookup_table.values()]#It is just a true/false list
    if True in chks and chks.count(True)==1:
      v= lookup_table[chks.index(True)+1]
      for ky,vl in lookup_table.iteritems():
        if vl == v:
          return str(ky)
  except:
    return 'N/A'

And run it-

labeller(!firstCol!)

N.B. I used OrderedDict for performance - you can use normal dictionary too.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.