I am new to python and would like to have a script that looks at a feature class and compares the values in two text fields and then populates a third field with a Y or N depending on if the values are the same or not. I think I need to use an UpdateCursor with an if statement. I have tried the following but I get a syntax error when I try to run it. I am using ArcGIS 10.1 and know that the daCursor is better but I am just trying to wrap my head around cursors and thought I would try and keep it simple for now.
#import system modules
import arcpy
from arcpy import env
import os
import sys
#set environment settings
working_fc = sys.argv[1]
working_gdb = os.path.split(working_fc)[0]
#use an update cursor to populate the field BEC_UPDATED based on the result of a query
#query = ("SELECT * FROM working_fc" "WHERE [BEC_LABEL] = [BEC_V9]")
#if the query is true, then BEC_UPDATED should be popluated with "N"
#if the query is false, then BEC_UPDATED should be populated with "Y"
rows = arcpy.UpdateCursor (working_fc)
for row in rows:
if row.getValue("BEC_LABEL") == row.getValue("BEC_V9")
row.BEC_UPDATED = "N"
else
row.BEC_UPDATED = "Y"
rows.updateRow(row)
print "BEC_UPDATED field populated"
Your syntax error is caused by indentation and missing colons. Python is picky about that, so always check that when you're getting a syntax error.
rows = arcpy.UpdateCursor(working_fc)
for row in rows:
if row.getValue("BEC_LABEL") == row.getValue("BEC_V9"):
row.BEC_UPDATED = "N"
else:
row.BEC_UPDATED = "Y"
rows.updateRow(row)
Changing this to the da.UpdateCursor syntax is essentially the same, but requires you to specify the attributes you are interested in up front. It's worth practicing, because once you get into more complex scripts it will become easier :)
fieldList = ["BEC_LABEL", "BEC_V9", "BEC_UPDATED"]
with arcpy.da.UpdateCursor(working_fc, fieldList) as cursor:
for row in cursor:
if row[0] == row[1]:
row[2] = "N"
else:
row[2] = "Y"
cursor.updateRow(row)
You've forgotten the colons and indentation in your 'if' block:
rows = arcpy.UpdateCursor (working_fc)
for row in rows:
if row.getValue("BEC_LABEL") == row.getValue("BEC_V9"):
row.BEC_UPDATED = "N"
else:
row.BEC_UPDATED = "Y"
rows.updateRow(row)
print "BEC_UPDATED field populated"
Related
I am trying to loop through and count how many times 'Dan' has the color 'green'
my sheet looks like this
https://imgur.com/a/ccohMbD
import xlrd
import os
#os.chdir('C:\Users\Dan\Desktop')
cwd = os.getcwd()
excelsheet1 ='Python practice book.xlsx'
book1 = xlrd.open_workbook(excelsheet1)
sheet = book1.sheet_by_index(0)
i=0
for row in range(sheet.nrows):
if str(sheet.cell(row,0).value) == "Dan" and 'green':
i=i+1
else:
pass
print('there are', i)
In this it tells me 2, Which I understand is because python is only looping for Dan and not taking into account my and function.
I have tried duplicating my if function using code:
if str(sheet.cell(row,0).value) == "Dan":
if str(sheet.cell(row,0).value) == "green":
i=i+1
else:
pass
print('there are', i)
which python returns 0
I think its related to how I am formatting my call
As Klaus commented, "and" doesn't work like that. In the case of a non empty string, it will always return True.
The example below will return your expected results. I set the "name" and "color" variables to enhance readability.
Note that your second code example would have worked fine, except that you didn't change the column index between the first "if" and the second.
import xlrd
import os
#os.chdir('C:\Users\Dan\Desktop')
cwd = os.getcwd()
excelsheet1 ='Python practice book.xlsx'
book1 = xlrd.open_workbook(excelsheet1)
sheet = book1.sheet_by_index(0)
i=0
for row in range(sheet.nrows):
name = str(sheet.cell(row,0).value)
color = str(sheet.cell(row,2).value)
if name == "Dan" and color == "green":
i=i+1
# There's no need for an "else" statement here.
print('there are', i)
I am having an issue where I need to access variables from one script in another. I've searched this question and I understand that we can use import to access variables in another script. The data is coming from an Arduino and is sent to a Raspberry Pi via serial and the values are continuous until the script is stopped. I have put my code into a function and I need to return the sensor data continuously.
values.py script:
import datetime
import serial
datetime.datetime.now()
ser=serial.Serial('/dev/ttyACM0',115200)
def printVal():
while True:
read_serial=ser.readline()
val= read_serial.decode()
val =val.strip()
row = [x for x in val.split(' ')]
if len(row) == 6:
#p = ('Sensor1:',row[0], 'Sensor2:',row[1], 'Sensor3:',row[2], 'Sensor4:',row[3], 'Sensor5:',row[4], 'Sensor6:',row[5])
#print (row)
#return row
sensor1= row[0]
sensor2 = row[1]
sensor3 = row[2]
sensor4 = row[3]
sensor5 = row[4]
sensor6 = row[5]
#print (sensor1, sensor2, sensor3, sensor4, sensor5, sensor6)
return (sensor1)
printVal()
second.py script:
from values import printVal
print (printVal())
I need to include the if len(row)==6 statement because the first line that prints will be three values and the other values will be out of the index.
My question is how would I access each individual array value in the second script. Would I need to print the function, I am confused on how to do this. I think the return statement is causing only one value to print and not be continuous.
You can use the json format to pass a single variable, an array, a hashmap.
For continuous transmisssion, you can read the data line by line and decode/load the data once a line is completed.
The documentation with examples :
python2 https://docs.python.org/2/library/json.html
python3 https://docs.python.org/3/library/json.html
You can return a dictionary from your printVal() function.
def printVal():
# your logic here to get sensor data
sensor_data = {'sensor1': row[0],
'sensor2': row[1],
'sensor3': row[2],
'sensor4': row[3],
'sensor5': row[4],
'sensor6': row[5]
}
return sensor_data
Then you can assign the return values to a variable in your second script like so:
from values import printVal
sensor_data = printVal()
print(sensor_data['sensor1'])
print(sensor_data['sensor6'])
I am new to Python. I am currently working on an app that fetches data from a Data table based on the users input. So far I can't seem to find the right set of commands anywhere. Does anyone have any tips?
In more technical terms the idea is this - user inputs data, user submits, query, fetch and retrieve, prints result... any ideas?
If you are using an XLSX file, the answer posted here (openpyxl find cell or row by value) has a way to find a row based on a specific value in a cell.
If it is a CSV file, you may need to read it and create a dictionary if there is a column of unique keys, otherwise iterate through every row each time a search term is entered.
Below is a solution that should give you some ideas. NOTE I use StringIO just for the example so that I didn't have to use a file and so that the example would work out of the box. You can modify the code to read from an Excel file, Pandas DataFrame, database or any other type of storage. That choice is yours.
import csv
import StringIO
data = """date,obs1,obs2
2017-01-01,23.2,30.2
2017-02-01,14.9,13.3
"""
buffer = StringIO.StringIO()
buffer.write(data)
buffer.seek(0)
def select_action():
menu = """Would you like to: (select a number)
1) See all data?
2) See data for a specific date?
3) Exit
-->"""
action = raw_input(menu)
while action.strip() not in ['1', '2', '3']:
print "ERROR: Invalid action"
action = raw_input(menu)
def do_action(action):
if action == '1':
reader = csv.reader(buffer)
for line in reader:
print "\t".join(field for field in line)
elif action == '2':
reader = csv.DictReader(buffer)
date = raw_input("Select date: ").strip()
for line in reader:
if date == line['date']:
output = ''
for k, v in line.items():
output += ("%s: %s " % (k, v))
print output
# You could write a case for action 3, but it isn't necessary
# the way I've written the code.
print "Goodbye"
def run():
action = select_action()
do_action(action)
I am creating a python script where I am trying to iterate over point feature class. I want to create seperate Feature classes from each individual day. So select daynumber and then export it to a new FC with an unique daynumber as name.
I was unable to find my answer online. So I decided to ask my question here.
ArcGIS 10.2
My script looks as follows:
test1 = "D:\\Mijn_Doc\\Test_Geodatabase.gd\\test1"
dayno = 2618
with test1 as rows:
for row in rows:
query = '"daynumber = '+ str(dayno) + '"'
arcpy.Select_analysis(test1, 'D:\\Mijn_Doc\\Test_Geodatabase.gdb\\select'+str(dayno), query)
dayno +=1
The error I get is:
arcgisscripting.ExecuteError: ERROR 000358: Invalid expression "daynumber = 2618"
Failed to execute (Select)
the selection looks fine, If I build it in Model Builder and export it to a Python script the expression looks the same as it looks in this Error message.
Any help will be appreciated.
Ashalynd, your advice was part of the solution, many thanks for that
This was the (working) script I was looking for:
dayno = 2618
with arcpy.da.SearchCursor(test1, ('daynumber',)) as cursor:
for row in cursor:
query= query='daynumber=%s' % dayno
if dayno > 2630:
break
else:
arcpy.Select_analysis(test1, selecttest + str(dayno), query)
dayno +=
I am trying to create and calculate a field called Score in an attribute table. Score would depend on two other fields, Width and Category. Width contains integer values, Category contains text. The Score field should assign a number of points based on the values of these two fields.
I was able to write a Python script assign values to SCORE based on the value of Width. However, once I tried to add Category as a parameter, I kept getting error messages saying that the parameters are not valid.
The code below worked (Width only):
expression = "getClass(float(!Width!))"
codeblock = """def getClass(wd):
if wd<=450:
return 1
elif wd>450 and wd<900:
return 2
else:
return 3"""
arcpy.AddField_management("featurelayer", "Score", "SHORT")
This code includes Category as a parameter and does not work:
expression = "getClass(!Width!,!Category!)"
codeblock = """def getClass(wd,cat):
if wd<=35:
return 1
elif wd<90 and cat=='RED':
return 2
else:
return 3"""
arcpy.AddField_management("featurelayer", "Score", "SHORT")
Thank you!
***I did try converting the two parameters in the second code - I tried float() for both, as well as str() for Category since it is a text field. Neither one worked, and the error messages were not very specific: "failed to execute getClass()"
***The Category field is completely populated (either 'RED' or 'BLUE')
Using the expression and codeblock method is necessary within ArcMap's Field Calculator, but not when writing a Python script.
Try an UpdateCursor instead. It is easier to read, and tends to be easier to debug as a result.
arcpy.AddField_management("featurelayer", "Score", "SHORT")
updateFields = ["Width", "Category", "Score"]
with arcpy.da.UpdateCursor("featurelayer", updateFields) as cursor:
for row in cursor:
if row[0] <= 35:
row[2] = 1
elif row[0] < 90 and row[1] == 'RED':
row[2] = 2
else:
row[2] = 3
cursor.updateRow(row)