Skip to main content
Solved

Finding change in a feature's attributes

  • February 3, 2015
  • 7 replies
  • 10 views

Hello, 

 

 

i have a many 1000s of point features with some time series data. Each point has a CODE attribute column for 2000 to 2010 inclusive (CODE01, CODE 02, CODE03 .... CODE10). These code attributes can be one of 10 entries (1,2,4,8,16,32,64,128, 256 or empty).

 

 

I need to look over the attributes in year order for a given feature and ascertain how many times the code value has changed in those 11 given years. 

 

 

EG;

 

 

 

so you can see Feature 1 would have a new attribute recording 0 changes, feature 2 would have 2 changes (to 64 and back to 32), feature 3 would have 7 changes and feature 4 would have 5 changes (missing does count as a change).

 

 

I thought perhaps i should transpose the data? have each feature exploded into 11 features, one for each year, and then use the Multiple Feature Attribute Support (using Feature(-1) etc) but if im dealing with a million points, that will make 11 millions points. Is there any way of dealing with a previous attribute in a similar way?

 

 

all help much appreciated

 

 

Best answer by takashi

Hi,

 

 

Two AttributeCreators do that without exploding features.

 

In the first one, create an attribute (e.g. named "count"), and set 0.

 

In the second one, set 10 conditional value settings to count changes between every adjacent two attributes.

 

count = If CODE01 != CODE00 Then count + 1 Else <No Action>

 

count = If CODE02 != CODE01 Then count + 1 Else <No Action>

 

...

 

count = If CODE10 != CODE09 Then count + 1 Else <No Action>

 

 

Since the AttributeCreator evaluates every expression in the order from top to bottom, finally the "count" attribute will store the number of changes. 

 

 

But it may be too tedious. Python or Tcl scripting could be better solution.

 

-----

 

# Script Example for PythonCaller

 

def countChange(feature):

 

    count = 0

 

    v0 = feature.getAttribute('CODE00')

 

    for i in range(1,11):

 

        v1 = feature.getAttribute('CODE%02d' % i)

 

        if v1 != v0:

 

            count += 1

 

        v0 = v1

 

    feature.setAttribute('_count', count)

 

-----

 

# Script Example for TclCaller

 

proc countChange {} {

 

    set count 0

 

    set v0 [FME_GetAttribute "CODE00"]

 

    for {set i 1} {$i < 11} {incr i} {

 

        set v1 [FME_GetAttribute "CODE[format %02d $i]"]

 

        if  {$v1 != $v0} {incr count}

 

        set v0 $v1

 

    }

 

    return $count

 

}

 

-----

 

 

Takashi
View original
Did this help you find an answer to your question?
This post is closed to further activity.
It may be a question with a best answer, an implemented idea, or just a post needing no comment.
If you have a follow-up or related question, please post a new question or idea.
If there is a genuine update to be made, please contact us and request that the post is reopened.

7 replies

takashi
Influencer
  • Best Answer
  • February 3, 2015
Hi,

 

 

Two AttributeCreators do that without exploding features.

 

In the first one, create an attribute (e.g. named "count"), and set 0.

 

In the second one, set 10 conditional value settings to count changes between every adjacent two attributes.

 

count = If CODE01 != CODE00 Then count + 1 Else <No Action>

 

count = If CODE02 != CODE01 Then count + 1 Else <No Action>

 

...

 

count = If CODE10 != CODE09 Then count + 1 Else <No Action>

 

 

Since the AttributeCreator evaluates every expression in the order from top to bottom, finally the "count" attribute will store the number of changes. 

 

 

But it may be too tedious. Python or Tcl scripting could be better solution.

 

-----

 

# Script Example for PythonCaller

 

def countChange(feature):

 

    count = 0

 

    v0 = feature.getAttribute('CODE00')

 

    for i in range(1,11):

 

        v1 = feature.getAttribute('CODE%02d' % i)

 

        if v1 != v0:

 

            count += 1

 

        v0 = v1

 

    feature.setAttribute('_count', count)

 

-----

 

# Script Example for TclCaller

 

proc countChange {} {

 

    set count 0

 

    set v0 [FME_GetAttribute "CODE00"]

 

    for {set i 1} {$i < 11} {incr i} {

 

        set v1 [FME_GetAttribute "CODE[format %02d $i]"]

 

        if  {$v1 != $v0} {incr count}

 

        set v0 $v1

 

    }

 

    return $count

 

}

 

-----

 

 

Takashi

gio
Contributor
Forum|alt.badge.img+15
  • Contributor
  • February 3, 2015
Or, by using transformers:

 

 

 

 

Using the listpopulator and a customloop..

 

 


  • Author
  • February 3, 2015
thanks both.

 

 

Takashi: I have set up the Creators but in the 2nd one with conditionals, I am getting no further than 1 in the 'count' attribute (it does remain 0 where no change at all occurs - correctly), it seems to not bother with the remaining rules should one be satisfied;

 

 


takashi
Influencer
  • February 3, 2015
Looks like you are using FME 2014.

 

Such a waterfall-like continuous calculation in the AttributeCreator can be performed in FME 2015, but it may not work in FME 2014 unfortunately.

 

 

Well, here is another thought.

 

Use the NullAttributeMapper to replace every Missing attribute with 0.

 

Then, this long expression in the ExpressionEvaludator or the AttributeCreator returns the required number.

 

-----

 

(@Value(CODE00)!=@Value(CODE01)?1:0)

 

+(@Value(CODE01)!=@Value(CODE02)?1:0)

 

+(@Value(CODE02)!=@Value(CODE03)?1:0)

 

+(@Value(CODE03)!=@Value(CODE04)?1:0)

 

+(@Value(CODE04)!=@Value(CODE05)?1:0)

 

+(@Value(CODE05)!=@Value(CODE06)?1:0)

 

+(@Value(CODE06)!=@Value(CODE07)?1:0)

 

+(@Value(CODE07)!=@Value(CODE08)?1:0)

 

+(@Value(CODE08)!=@Value(CODE09)?1:0)

 

+(@Value(CODE09)!=@Value(CODE10)?1:0)

 

-----

 

 

After that, replace 0 attribute with Missing with the second NullAttributeMapper, if necessagy.

takashi
Influencer
  • February 3, 2015
In this case, the ^ operator (bit wise exclusive OR) can also be used instead of the != operator. FYI.

 

-----

 

(@Value(CODE00)^@Value(CODE01)?1:0)

 

+(@Value(CODE01)^@Value(CODE02)?1:0)

 

...

 

+(@Value(CODE09)^@Value(CODE10)?1:0)

 

-----

  • Author
  • February 3, 2015
Thanks Takashi, i upgraded to FME 2015 and your original answer worked  :)

gio
Contributor
Forum|alt.badge.img+15
  • Contributor
  • February 3, 2015
Hi,

 

 

Here is one without loop, still based on lispopulator. (and replacing of Empty/null/missing attributes due to inefficiency of listpopulator)

 

 

 

 

more efficient and elegant.

 

 

If you would prevent Null/Missing/EMPTY attributes then no NullAttributeMapper would be nescessary and there would be no need for any "manual labor"

 

 

 

Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings