Solved

Finding change in a feature's attributes

  • 3 February 2015
  • 7 replies
  • 4 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

 

 
icon

Best answer by takashi 3 February 2015, 13:20

View original

7 replies

Userlevel 2
Badge +17
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
Badge +3
Or, by using transformers:

 

 

 

 

Using the listpopulator and a customloop..

 

 

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;

 

 

Userlevel 2
Badge +17
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.
Userlevel 2
Badge +17
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)

 

-----
Thanks Takashi, i upgraded to FME 2015 and your original answer worked  :)
Badge +3
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"

 

 

 

Reply