Skip to content

Instantly share code, notes, and snippets.

@timyates
Forked from anonymous/Reshape.md
Last active December 17, 2015 16:59
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save timyates/5642622 to your computer and use it in GitHub Desktop.

From the simple R example of reshape here, given a List of Maps like this:

data = [ [ id: 1, time: 1, x1: 5, x2: 6 ],
         [ id: 1, time: 2, x1: 3, x2: 5 ],
         [ id: 2, time: 1, x1: 6, x2: 1 ],
         [ id: 2, time: 2, x1: 2, x2: 4 ] ]

And the methods melt:

List melt( List data, List keys ) {
  data.collectMany {
    it.subMap( keys ).with { k ->
      ( it - k ).inject( [] ) { r, v -> 
        r << ( k + [ key:v.key, value:v.value ] )
      }
    }
  }
}

and cast:

List cast( List data, String subject, Closure fn ) {
  data.groupBy( { it[ subject ] } ).collect { k, v ->
    v.groupBy( { it[ 'key' ] } ).collectEntries { k2, v2 ->
      fn( v2.value ).with { f ->
        [ (subject): k, (k2): f ]
      }
    }
  }
}

We can first melt our data with:

def a = melt( data, [ 'id', 'time' ] )

Which gives us the List of Maps:

[ [ id:1, time:1, key:x1, value:5 ],
  [ id:1, time:1, key:x2, value:6 ],
  [ id:1, time:2, key:x1, value:3 ],
  [ id:1, time:2, key:x2, value:5 ],
  [ id:2, time:1, key:x1, value:6 ],
  [ id:2, time:1, key:x2, value:1 ],
  [ id:2, time:2, key:x1, value:2 ],
  [ id:2, time:2, key:x2, value:4 ] ]

We can then get the mean value of x1 and x2 by id using:

/*
 [ [ id:1, x1:4, x2:5.5 ],
   [ id:2, x1:4, x2:2.5 ] ]
*/
def avgById = cast( a, 'id' ) {
  it.sum() / it.size()
}

Or by time by:

/*
 [ [ time:1, x1:5.5, x2:3.5 ],
   [ time:2, x1:2.5, x2:4.5 ] ]
*/
def avgByTime = cast( a, 'time' ) {
  it.sum() / it.size()
}
@timyates
Copy link
Author

This is obviously a first pass, only taking the simplest of examples of what reshape can do. Much more work required

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment