0

I have a indoor positioning shp file. I need to do the data cleaning for the further analysis. and here is the attribute table: Field(Sheet1_minor) is the name of beacon, and Fields(Beacon_41_B1,B2,B3,B4) which are near the beacon(Sheet_minor)

Field(Sheet1_minor) is the name of beacon, and Fields(Beacon_41_B1,B2,B3,B4) which are near the beacon(Sheet_minor). I am trying to clean the noise data by filtering the same record or adjacent record. For example, i start to work from ObjectID 28, I want to testify if ID 29 value of field(Sheet_minor) is equal to ID 28 adjacent record(Beacon47_B1,B2,B3,B4).

  • Yes->

testify ID 28 value of field(Sheet_minor) == ID 30 value of field(Sheet_minor), if this equation is true,delete ID29 and ID30. if this equation is false, skip it.

  • No->

skip this record. Here is my code, but it doesn't seem to work.

# Licence:     <ArcGIS 10.3.1>
# Import python modules
import arcpy,sys
from arcpy import env

# set the workspace enviroment
env.workspace = r"D:\KKC\Indoor positioning\Ni_Feature\Ni_shp.gdb"
# To aviod an error, set the geoprocessing environment to allow existing data to be overwritten.
env.overwriteOutput = True
# Create a variable with the name of the subject feature class
fcName = "User1_test"
rows = arcpy.UpdateCursor(fcName)
fields = arcpy.ListFields(fcName)
# print out the fields in table
#    with arcpy.da.SearchCursor(fcName,["Sheet1__minor"]) as cursor:
for row in rows:
    for field in fields:
        if fields.getValue(field.Sheet1__minor) == fields.getValue(field.Beacon_47_B1) or fields.getValue(field.Sheet1__minor) == fields.getValue(field.Beacon_47_B2) or fields.getValue(field.Sheet1__minor) == fields.getValue(field.Beacon_47_B3) or fields.getValue(field.Sheet1__minor) == fields.getValue(field.Beacon_47_B4):
            if rows.getValue(field.Sheet1__minor) == rows.getValues(field.Sheet1__minor) + 2 :
                cursor.deleteRow()
            else:
                pass
                rows.updateRow(row)
        else:
            pass


-------------------------------------------
Traceback (most recent call last):
  File "<module1>", line 30, in <module>
AttributeError: 'list' object has no attribute 'getValue'
------------------------------------------ 

this is the message. I think i create the list for fields and rows.

Do you have any suggestion?

  • 2
    I suggest removing all the lines that have been commented out - they are just noise in a code snippet. Also remove the try/except block that just masks error messages in a code snippet. Run a more minimal code snippet and show here precisely what you ran and precisely what it output. As one of the potential answerers of your question please be aware that I am usually happy to look at code snippets but I never do much more than glance at people's code if they do not reduce it first. – PolyGeo Jun 7 '16 at 3:39
  • 2
    "it doesn`t seem to work" - what does it do? Nothing at all? Give lots of errors? take a long time and then you kill it? Please add a bit of info about what is happening as that makes it easier for us to understand the problem and offer suggestions to fix – Midavalo Jun 7 '16 at 4:23
3

A cursor is organized like a list of tuples, like

[(field_1, field_2, field_3), (field_1, field_2, field_3), (field_1, field_2, field_3)]

When you use for row in cursor:, row becomes equivalent to (field_1, field_2, field_3). If you want to reference a specific item in the row, you would use the index for the value you want, thus row[0] is equivalent to the value for 'field_1'.

arcpy.ListFields returns a list of field objects, an arcpy class object that contains all of the information about that field (data type, length, precision, name, etc). Based on your question, you would probably be better suited to specify the names of your fields as input for the cursor, like

fields = ['Sheet1_minor', 'Beacon_47_B1', 'Beacon_47_B2', 'Beacon_47_B3', 'Beacon_47_B4', 'ObjectID']

If you don't know the names of the fields, or want to check your spelling, or perhaps you want to just use all the fields, you can use:

fields = [fld.name for fld in arcpy.ListFields(fcName)]

Which will give you a list of the name attributes for each field object that is returned by ListFields.

Based on your question it seems like you're trying to specifically access rows before and after the current row; you can do this with the built in function enumerate(list) in python, though I've never used it on an arcpy cursor (https://docs.python.org/2/library/functions.html#enumerate).

If you're not worried about iterating through your data a few times, you could first build a list of ObjectIDs whose Sheet1_minor values are shared by both the previous and the subsequent ObjectID, then reference the list of ObjectIDs in your Update cursor to know when to delete them.

fcName = "User1_test"
fields = ['Sheet1_minor', 'Beacon_47_B1', 'Beacon_47_B2', 'Beacon_47_B3', 'Beacon_47_B4', 'ObjectID']
data_dict = {row[5]:[row[0], row[1], row[2], row[3], row[4]] for row in arcpy.da.SearchCursor(fcName, fields)}
the_bad_list = [row[5] for row in arcpy.da.SearchCursor(fcName, fields) if row[5] > 28 and (row[0] == data_dict[row[5]-1] and row[0] == data_dict[row[5]+1])]
with arcpy.da.UpdateCursor(fcName, fields) as cursor:
    for row in cursor:
        if row[0] in [row[1], row[2], row[3], row[4]] and row[5] > 28:
            if row[5] in the_bad_list:
                cursor.deleteRow()
            else: continue
        else: continue

This code should:

1) Make a dictionary that stores the relevant information in your table

2) build a list of ObjectIDs whose Sheet1_minor value is shared by both the previous and subsequent rows

3) Delete rows in the table where the ObjectIDs are in the_bad_list

Based on your logic this should delete ObjectIDs 29 through 44 in your table. It's not the most efficient methodology, but with 8700 rows it shouldn't take too long.

arcpy.da.SearchCursor (http://pro.arcgis.com/en/pro-app/arcpy/data-access/searchcursor-class.htm)

2

Your error is coming from:

fields.getValue(field.Sheet1__minor)

your variable fields is a list object that is holding a list of field objects.

Python list objects do not have a getValue method.

Consequently the error message that you are receiving is to be expected:

AttributeError: 'list' object has no attribute 'getValue'

2

Another error may come from:

cursor.deleteRow() 

This line should be:

rows.deleteRow()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.