<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Calculating ratio between “rows” in ArcGIS field calculator in ArcMap Questions</title>
    <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049465#M2378</link>
    <description>&lt;P&gt;Didn't know about itertools.tee, seems cool but honestly a little confusing.&lt;/P&gt;&lt;P&gt;I'd have done that by storing the previous value in a variable.&lt;/P&gt;</description>
    <pubDate>Wed, 21 Apr 2021 05:10:07 GMT</pubDate>
    <dc:creator>JohannesLindner</dc:creator>
    <dc:date>2021-04-21T05:10:07Z</dc:date>
    <item>
      <title>Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049036#M2363</link>
      <description>&lt;DIV class="s-prose js-post-body"&gt;&lt;P&gt;I have to calculate the Ratio between rows (sequentially, i.e., row1/row2, row2/row3 and so on) of a specific field based on the ID field and have to assign the results to a separate field.&lt;/P&gt;&lt;P&gt;Here is the code and the error message:&lt;/P&gt;&lt;PRE&gt; &lt;SPAN class="hljs-function"&gt;&lt;SPAN class="hljs-keyword"&gt;def&lt;/SPAN&gt; &lt;SPAN class="hljs-title"&gt;CalcRatio&lt;/SPAN&gt;(&lt;SPAN class="hljs-params"&gt;ID,Frequency&lt;/SPAN&gt;&lt;span class="lia-unicode-emoji" title=":disappointed_face:"&gt;😞&lt;/span&gt;&lt;/SPAN&gt;
    vDict = {}
    &lt;SPAN class="hljs-keyword"&gt;with&lt;/SPAN&gt; arcpy.da.SearchCursor(&lt;SPAN class="hljs-string"&gt;"Test"&lt;/SPAN&gt;,[&lt;SPAN class="hljs-string"&gt;'Frequency'&lt;/SPAN&gt;],&lt;SPAN class="hljs-string"&gt;'ID = {}'&lt;/SPAN&gt;.&lt;SPAN class="hljs-built_in"&gt;format&lt;/SPAN&gt;(ID)) &lt;SPAN class="hljs-keyword"&gt;as&lt;/SPAN&gt; sCur:
    &lt;SPAN class="hljs-keyword"&gt;for&lt;/SPAN&gt; Row &lt;SPAN class="hljs-keyword"&gt;in&lt;/SPAN&gt; sCur:
    vDict[Row[&lt;SPAN class="hljs-number"&gt;0&lt;/SPAN&gt;]]=Row[&lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt;] &lt;SPAN class="hljs-comment"&gt;# Dict[id] =Frequency&lt;/SPAN&gt;
    &lt;SPAN class="hljs-keyword"&gt;try&lt;/SPAN&gt;: value = ( vDict[&lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt;] / vDict[&lt;SPAN class="hljs-number"&gt;2&lt;/SPAN&gt;])
    &lt;SPAN class="hljs-keyword"&gt;except&lt;/SPAN&gt;: value = -&lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt;
    &lt;SPAN class="hljs-keyword"&gt;return&lt;/SPAN&gt; value&lt;/PRE&gt;&lt;P&gt;Message:&lt;/P&gt;&lt;PRE&gt;ERROR 000539: Error running expression: CalcRatio( &lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt; , &lt;SPAN class="hljs-number"&gt;50680&lt;/SPAN&gt;) Traceback (most recent call last):
File &lt;SPAN class="hljs-string"&gt;"&amp;lt;expression&amp;gt;"&lt;/SPAN&gt;, line &lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt;,
&lt;SPAN class="hljs-keyword"&gt;in&lt;/SPAN&gt; &amp;lt;module&amp;gt; File &lt;SPAN class="hljs-string"&gt;"&amp;lt;string&amp;gt;"&lt;/SPAN&gt;, line &lt;SPAN class="hljs-number"&gt;5&lt;/SPAN&gt;,
&lt;SPAN class="hljs-keyword"&gt;in&lt;/SPAN&gt; CalcRatio IndexError: &lt;SPAN class="hljs-built_in"&gt;tuple&lt;/SPAN&gt; index out of &lt;SPAN class="hljs-built_in"&gt;range&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;P&gt;Here is the data&lt;/P&gt;&lt;PRE&gt;OID Id  Frequency
&lt;SPAN class="hljs-number"&gt;0&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;50680&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;1&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;2&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;49740&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;2&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;3&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;48620&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;3&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;4&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;48300&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;4&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;5&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;48004&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;5&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;6&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;45600&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;6&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;7&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;44384&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;7&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;8&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;42720&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;8&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;9&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;41890&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;9&lt;/SPAN&gt;   &lt;SPAN class="hljs-number"&gt;10&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;39700&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;10&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;11&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;38530&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;11&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;12&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;38207&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;12&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;13&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;38106&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;13&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;14&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;37303&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;14&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;15&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;37205&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;15&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;16&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;36527&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;16&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;17&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;35301&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;17&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;18&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;31674&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;18&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;19&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;28890&lt;/SPAN&gt;
&lt;SPAN class="hljs-number"&gt;19&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;20&lt;/SPAN&gt;  &lt;SPAN class="hljs-number"&gt;24612&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/DIV&gt;&lt;DIV class="mt24 mb12"&gt;&lt;DIV class="post-taglist grid gs4 gsy fd-column"&gt;&lt;DIV class="grid ps-relative"&gt;&lt;A title="show questions tagged 'arcgis-desktop'" href="https://gis.stackexchange.com/questions/tagged/arcgis-desktop" target="_blank" rel="noopener tag"&gt;arcgis-desktop&lt;/A&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Tue, 20 Apr 2021 11:50:03 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049036#M2363</guid>
      <dc:creator>badrinathkar</dc:creator>
      <dc:date>2021-04-20T11:50:03Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049071#M2366</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;# The error is thrown by this line:
vDict[Row[0]]=Row[1] # Dict[id] =Frequency

# You only use one field (Frequency) in your cursor, so Row is a list with only one entry.&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Personally, I hate using field calculator to calculate values based on multiple rows. I'd rather use pure Python:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;# extract all rows and sort by ID
# data = [ [ID, Freq], [ID, Freq], ... ]
data = [row for row in arcpy.da.SearchCursor("Test", ["ID", "Frequency"])]
data.sort(key = lambda d: d[0])

# do the calculation
for i in range(len(data)):
    try:
        value = data[i][1] / data[i+1][1]
    except:
        # instead of catching all exceptions, you could also just catch the ones you expect:
        # last element will raise IndexError
        # Freq == NULL will raise TypeError
        # Freq == 0 will raise ZeroDivisionError
        value = -1
    data[i].append(value)

# convert data into a lookup dictionary
# data = {ID: value, ID: value, ...}
data = {d[0]: d[2] for d in data}

# write the results into the table
with arcpy.da.UpdateCursor("Test", ["ID", "ValueField"]) as cursor:
    for id, value in cursor:
        try:
            new_value = data[id]
        except KeyError:
            new_value = -1
        cursor.updateRow([id, new_value])&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 20 Apr 2021 13:14:09 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049071#M2366</guid>
      <dc:creator>JohannesLindner</dc:creator>
      <dc:date>2021-04-20T13:14:09Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049327#M2367</link>
      <description>&lt;P&gt;I agree with &lt;a href="https://community.esri.com/t5/user/viewprofilepage/user-id/294341"&gt;@JohannesLindner&lt;/a&gt; that this is best handled using cursors instead of Field Calculator.&amp;nbsp; If you are interested in doing a "look-behind" calculation, you can do it with a single pass of an update cursor.&lt;/P&gt;&lt;LI-CODE lang="python"&gt;from itertools import tee

tbl = # path to table or feature class
with arcpy.da.UpdateCursor(tbl, ["Frequency", "value"], sql_clause=(None, "ORDER BY Id")) as cur:
    n1, n = tee(cur)
    row_n1 = next(n1)
    for row_n1 in n1:
        row_n = next(n)
        cur.updateRow([row_n1[0], row_n[0]/row_n1[0]])&lt;/LI-CODE&gt;</description>
      <pubDate>Tue, 20 Apr 2021 19:46:38 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049327#M2367</guid>
      <dc:creator>JoshuaBixby</dc:creator>
      <dc:date>2021-04-20T19:46:38Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049465#M2378</link>
      <description>&lt;P&gt;Didn't know about itertools.tee, seems cool but honestly a little confusing.&lt;/P&gt;&lt;P&gt;I'd have done that by storing the previous value in a variable.&lt;/P&gt;</description>
      <pubDate>Wed, 21 Apr 2021 05:10:07 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049465#M2378</guid>
      <dc:creator>JohannesLindner</dc:creator>
      <dc:date>2021-04-21T05:10:07Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049555#M2379</link>
      <description>&lt;P&gt;There are a couple of handy things about tee that aren't used in this simple situation.&amp;nbsp; For example, you can split an iterable into as many independent iterators as you like, it doesn't have to be just two.&amp;nbsp; Since the iterators are independent of each other, each can be at a various spot.&amp;nbsp; The tricky part with update cursors is that the furthest ahead iterator determines where the underlying cursor is in terms of the dataset, which is why "look-behind" calculations can be done but not "look-ahead" if you want to update the dataset in one pass.&lt;/P&gt;</description>
      <pubDate>Wed, 21 Apr 2021 14:07:23 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049555#M2379</guid>
      <dc:creator>JoshuaBixby</dc:creator>
      <dc:date>2021-04-21T14:07:23Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049564#M2381</link>
      <description>&lt;P&gt;Yeah, the cursor.updateRow was the most confusing thing.&lt;/P&gt;&lt;P&gt;Is this behavior specific to UpdateCursor/all arcpy.da.*Cursors? Or is this the expected behavior, that the child iterators are independent from each other, but not from the parent / the parent not from them?&lt;/P&gt;</description>
      <pubDate>Wed, 21 Apr 2021 14:19:39 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1049564#M2381</guid>
      <dc:creator>JohannesLindner</dc:creator>
      <dc:date>2021-04-21T14:19:39Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1053218#M2432</link>
      <description>&lt;P&gt;In this case, ArcPy cursors are simply iterables to tee, and the cursors are treated just like tee would treat any other iterable when splitting it.&lt;/P&gt;&lt;P&gt;The &lt;A href="https://docs.python.org/3/library/itertools.html#itertools.tee" target="_blank"&gt;itertools — Functions creating iterators for efficient looping — Python 3.9.4 documentation&lt;/A&gt; states:&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;Once tee() has made a split, the original iterable should not be used anywhere else; otherwise, the iterable could get advanced without the tee objects being informed.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;For ArcPy cursors, the iterators returned back from tee do not have an updateRow() method, which is why I refer back to the cursor object to update the row.&amp;nbsp; That said, you will notice that I am not iterating the original cursor because doing so would create a situation where the tee iterators miss rows of data.&lt;/P&gt;&lt;P&gt;ArcPy cursors are "forward-only" cursors, meaning they can only move one direction through the data set once defined.&amp;nbsp; Once the cursors has visited row x+1, it can't go back to row x unless the cursor is reset, which takes the cursor back to the start of the data set.&amp;nbsp; Since ArcPy cursors are forward-only, the tee iterator that is furthest through the data set determines where the original cursor object is in the data set.&lt;/P&gt;</description>
      <pubDate>Fri, 30 Apr 2021 15:11:55 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1053218#M2432</guid>
      <dc:creator>JoshuaBixby</dc:creator>
      <dc:date>2021-04-30T15:11:55Z</dc:date>
    </item>
    <item>
      <title>Re: Calculating ratio between “rows” in ArcGIS field calculator</title>
      <link>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1053673#M2446</link>
      <description>&lt;P&gt;Thanks for the explanation Joshua, really appreciate it.&lt;/P&gt;</description>
      <pubDate>Mon, 03 May 2021 05:41:03 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcmap-questions/calculating-ratio-between-rows-in-arcgis-field/m-p/1053673#M2446</guid>
      <dc:creator>JohannesLindner</dc:creator>
      <dc:date>2021-05-03T05:41:03Z</dc:date>
    </item>
  </channel>
</rss>

