Select to view content in your preferred language

Problems with deicimal point when calculating sum in script

755
3
12-18-2013 03:29 AM
RichardNilsson
Emerging Contributor
Hi!

First, I am very new to python! And not very skilled in programing at all. So bare with me, please! If there is anyone out there that might be interested in helping me, please be as basic as possible. 😉

Anyhow, I am trying to use a script in a toolbox I created. The script sums the rows in a field and fills the result in another field.
import arcgisscripting, sys
gp = arcgisscripting.create()

intable = sys.argv[1]
field = sys.argv[2]

# Create search cursor
rows = gp.SearchCursor(intable)
row = rows.Next()
x = 0.0
# Enter while loop for each feature/row
while row:
    x += row.getvalue(field)
    print x
    row = rows.next()
#note value can be rounded depending on field type
gp.calculatefield(intable,sys.argv[3],float(x),"PYTHON")


Kudos goes out to Terry Giles for posting this script here!

Both input and output fields, in the table, are set to be of the type Float.
Parameters in the properties are

Display Name - Data Type
-----------------------------------
Layer or Table - Table
Input Field - Field
Output Field - Field
Output Layer - Table
-----------------------------------

Parameter Properties

Display Name  - Property - Value
-----------------------------------
Layer or Table - Type         - Required
Layer or Table - Direction    - Input
Layer or Table - Multivalue   - No
Layer or Table - Filter          - None
-----------------------
Input Field      - Type          - Required
Input Field      - Direction     - Input
Input Field      - Multivalue    - No
Input Field      - Filter           - None
Input Field      - Obtained from - Layer or Table
-----------------------
Output Field    - Type               - Required
Output Field    - Direction          - Input
Output Field    - Multivalue         - No
Output Field    - Filter                - None
Output Field    - Obtained from    - Layer or Table
-----------------------
Output Layer    - Type        - Derived
Output Layer    - Direction    - Output
Output Layer    - Multivalue   - No
Output Layer     - Filter       - None

My problem is that the script only works for integers. All I get when calculating numbers containing a decimal point is null. At least that is what ends up in my field...

I had a suspicion that this might be a localization problem. The numbers used for calculation are in Swedish, i.e 8,2. Using a comma sign as decimal point. BUT, When i run a check on locales i get: getlocale =  ('Swedish_Sweden', '1252'), getdefaultlocale = ('sv_SE', 'cp1252') and getpreferredencoding = cp1252. Which, to me, looks correct. So that smashes my suspicion. 😞

I am using ArcGIS 10.1 SP1 for Desktop with standard license. This takes place on a Swedish installation, but set to show English. If I understand it correctly I am running Python 2.7.

I have searched through all possible forums in hunt for solution, my hope now goes out to you guys here!

Thanks in advance!
/Richard

Edit: The script runs in PyScript, but the output only shows periods instead of commas.
Tags (2)
0 Kudos
3 Replies
DouglasSands
Deactivated User
Not sure that this will resolve all the issues, but try the following code?

import arcpy

def main():
    #Set inputs
    feature = ''
    field = ''
    sum_field = ''
    
    #Get the sum
    total_val = sum([row[0] for row in arcpy.da.SearchCursor(feature, [field])])

    #Calculate the value
    table = arcpy.MakeTableView_management(feature, 'table')
    arcpy.CalculateField_management(table, sum_field, total_val, 'PYTHON_9.3')
    arcpy.Delete_management(table)
    return

if __name__ == '__main__':
    main()
    


The float() conversion isn't necessary since python will do this automatically if it sees float data.

Alternatively, if you save the following with a .pyt extension, ArcGIS will automatically recognize it as a toolbox:

import arcpy

class Toolbox(object):
    def __init__(self):
        self.label = 'Calculate Sum'
        self.alias = ''

        # List of tool classes associated with this toolbox
        self.tools = [CalculateSum]


class CalculateSum(object):
    def __init__(self):
        self.label = 'Calculate Sum'
        self.description = ''
        self.canRunInBackground = True

    def getParameterInfo(self):

        p0 = arcpy.Parameter(
                   name = "input_file",
                   displayName = "Input File",
                   datatype = "DEFeatureClass",
                   parameterType = "Required",
                   direction = "Input")

        p1 = arcpy.Parameter(
                   name = "value_field",
                   displayName = "Select Value Field",
                   datatype = "Field",
                   parameterType = "Required",
                   direction = "Input")
        
        p1.parameterDependencies = [p0.name]

        p2 = arcpy.Parameter(
                   name = "sum_field",
                   displayName = "Select Field to Populate",
                   datatype = "Field",
                   parameterType = "Required",
                   direction = "Input")
        
        p2.parameterDependencies = [p0.name]
        
        params = [p0, p1, p2]
        return params

    def isLicensed(self):
        '''Set whether tool is licensed to execute.'''
        return True

    def updateParameters(self, parameters):
        '''Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed.'''
        return

    def updateMessages(self, parameters):
        '''Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation.'''
        
        #Make it impossible for the two fields to be the same.
        if parameters[1].valueAsText == parameters[2].valueAsText:
            parameters[1].setErrorMessage("Value field cannot be the same as Populate Field.")
            parameters[2].setErrorMessage("Populate Field value cannot be the same as Value field.")
        return
    
    #Run the functions for this tool.
    def execute(self, params, messages):
        
        #Get the parameters
        feature, field, sum_field = [p.valueAsText for p in params]
        
        #Get the sum
        total_val = sum([row[0] for row in arcpy.da.SearchCursor(feature, [field])])

        #Calculate the value
        table = arcpy.MakeTableView_management(feature, 'table')
        arcpy.CalculateField_management(table, sum_field, total_val, 'PYTHON_9.3')
        arcpy.Delete_management(table)
        return



Hope this helps. Let me know if it doesn't work for you.
0 Kudos
RichardNilsson
Emerging Contributor
Hi Doug!

Thank you very much for your time!

I have tried both your scripts with different results.

The first script i tried directly on a table (dbf). When I calculate integers I just get the result 1. When there are decimal points involved I get an error message saying (Script run in PyScripter):
----------------------------------------------------------
Runtime error  Traceback (most recent call last):   File "<string>", line 19, in <module>   File "<string>", line 14, in main   File "c:\program files (x86)\arcgis\desktop10.1\arcpy\arcpy\management.py", line 3129, in CalculateField     raise e ExecuteError: ERROR 999999: Error executing function. The field is not nullable. [summa] Failed to execute (CalculateField).
----------------------------------------------------------

The second script (toolbox) returns the correct sum with integers but fails when it comes to decimal points. This is the error message:

----------------------------------------------------------
Executing: CalculateSum "K:\Gemensam\EU-projekt\Algae Be Gone\GIS\egna skikt\Biotopkartering Dk\tabort\New_Shapefile.shp" values summa
Start Time: Thu Dec 19 11:29:46 2013
Running script CalculateSum...

Traceback (most recent call last):
  File "<string>", line 79, in execute
  File "c:\program files (x86)\arcgis\desktop10.1\arcpy\arcpy\management.py", line 3129, in CalculateField
    raise e
ExecuteError: ERROR 999999: Error executing function.
The field is not nullable. [summa]
Failed to execute (CalculateField).


Failed to execute (CalculateSum).
Failed at Thu Dec 19 11:29:47 2013 (Elapsed Time: 1,00 seconds)
----------------------------------------------------------


Also, a bit off topic, the error message says elapsed time 1,00 seconds. But ArcMap i busy for at least 10 seconds before the computing fails.

I have attached both the shape file and the table I have used.

Hoping for more clues of what might be wrong here!

Regards,
Richard
0 Kudos
DouglasSands
Deactivated User
When I use your data the .pyt script 'works' for me, although the sum is incorrect (see picture).

Have you tried using a field type of double instead of float?

[ATTACH=CONFIG]30050[/ATTACH]
0 Kudos