Replies: 1 comment 1 reply
-
I really need to write those tutorials, but I need to do a lot of things! Here are some quick hints for how to get started, though the actual answer to your question will depend on exactly what you want to do. Starting with the bike routes (loading them as on what-is-awkward), >>> bikeroutes
<Record ... [-87.7, 42], [-87.7, 42]]]}}]} type='{"type": string, "crs": {"type"...'> In this particular GeoJSON file, all of the geometry elements are >>> bikeroutes["features", "geometry", "type"]
<Array ['MultiLineString', ... ] type='1061 * string'>
>>> bikeroutes["features", "geometry", "type"] == "MultiLineString"
<Array [True, True, True, ... True, True, True] type='1061 * bool'>
>>> ak.all(bikeroutes["features", "geometry", "type"] == "MultiLineString")
True If they differed, you'd be able to pick out one type with >>> only_multiline = bikeroutes["features", "geometry", "type"] == "MultiLineString"
>>> bikeroutes["features", "geometry", "coordinates", only_multiline]
<Array [[[[-87.8, 41.9], ... [-87.7, 42]]]] type='1061 * var * var * var * float64'> Once selected, the structure of the coordinates becomes more regular. In this case, the last "var" is always two elements, longitude and latitude. It can simplify things further along if we separate them early. >>> longitude = bikeroutes["features", "geometry", "coordinates", only_multiline][:, :, :, 0]
>>> latitude = bikeroutes["features", "geometry", "coordinates", only_multiline][:, :, :, 1]
>>> longitude, latitude
(<Array [[[-87.8, -87.8, ... -87.7, -87.7]]] type='1061 * var * var * float64'>,
<Array [[[41.9, 41.9, 41.9, ... 42, 42, 42]]] type='1061 * var * var * float64'>) Some slices can't be put in the same square brackets, such as alternating advanced indexes and basic indexes (because in trying to generalize what NumPy does, one of its rules is ambiguous in a non-rectilinear context), so we just put them in separate square brackets, as above. Anyway, now that we have arrays with type >>> longitude[:, :, 0]
<Array [[-87.8], [-87.7], ... [-87.8], [-87.7]] type='1061 * var * float64'>
>>> longitude[:, :, -1]
<Array [[-87.8], [-87.7], ... [-87.8], [-87.7]] type='1061 * var * float64'> or we could take the mean of each list: >>> ak.mean(longitude, axis=-1)
<Array [[-87.8], [-87.7], ... [-87.8], [-87.7]] type='1061 * var * ?float64'> There are a lot of reducers and reducer-like functions:
and I'll be adding The If instead of >>> ak.mean(longitude, axis=0)
<Array [[-87.7, -87.7, ... -87.6, -87.6]] type='7 * var * ?float64'> Notice that we have only 7 results. That's because the longest list in the first >>> ak.num(ak.mean(longitude, axis=0))
<Array [1980, 113, 97, 42, 167, 87, 3] type='7 * int64'> There are a lot of firsts, fewer seconds, even fewer thirds, and only 3 lists with all 7 elements. These are the lists of discontiguous paths: most paths are contiguous (having only one section), only only a few have a lot of discontiguous sections. We don't have an explicit "group by," but this is becoming possible because of some new functions like ak.argsort, ak.run_lengths, and ak.unflatten. See the Another "opposite of reduction" is padding. In some cases, you'll want to pad a dimension to equal lengths, rather than reducing the dimension away. Suppose, for instance, we want to take a mean over path segments but pad the number of path segments to 7. That is, starting from >>> ak.mean(longitude, axis=-1)
<Array [[-87.8], [-87.7], ... [-87.8], [-87.7]] type='1061 * var * ?float64'> we can look at the number of reduced elements in each, >>> ak.num(ak.mean(longitude, axis=-1))
<Array [1, 1, 1, 1, 1, 1, ... 1, 1, 1, 1, 1, 1] type='1061 * int64'> which looks like 1 everywhere, but actually there are a few that are more than 1: >>> ak.max(ak.num(ak.mean(longitude, axis=-1)))
7 The ak.pad_none function will pad them up to a given length: >>> ak.pad_none(ak.mean(longitude, axis=-1), 7)
<Array [[-87.8, None, None, ... None, None]] type='1061 * var * ?float64'>
>>> ak.num(ak.pad_none(ak.mean(longitude, axis=-1), 7))
<Array [7, 7, 7, 7, 7, 7, ... 7, 7, 7, 7, 7, 7] type='1061 * int64'> Note that if you also >>> ak.pad_none(ak.mean(longitude, axis=-1), 7, clip=True)
<Array [[-87.8, None, None, ... None, None]] type='1061 * 7 * ?float64'>
>>> # or 3 or whatever
>>> ak.pad_none(ak.mean(longitude, axis=-1), 3, clip=True)
<Array [[-87.8, None, None, ... None, None]] type='1061 * 3 * ?float64'> Now this is ready to be converted into a NumPy array with ak.to_numpy, >>> ak.to_numpy(ak.pad_none(ak.mean(longitude, axis=-1), 7, clip=True))
masked_array(
data=[[-87.78982910437593, --, --, --, --, --, --],
[-87.74850140064592, --, --, --, --, --, --],
[-87.61668302288385, --, --, --, --, --, --],
[-87.61225128042686, --, --, --, --, --, --],
[-87.61658216320194, --, --, --, --, --, --],
[-87.70704523129784, --, --, --, --, --, --],
[-87.70086075786773, --, --, --, --, --, --],
[-87.62536362791651, --, --, --, --, --, --],
[-87.62367290319223, --, --, --, --, --, --],
[-87.62215393620382, --, --, --, --, --, --],
[-87.60498403377314, --, --, --, --, --, --],
[-87.67312384621376, --, --, --, --, --, --],
[-87.69709189597117, --, --, --, --, --, --],
[-87.54187541007825, --, --, --, --, --, --],
[-87.69098199150667, --, --, --, --, --, --],
[-87.63376205750455, --, --, --, --, --, --],
[-87.59003505243615, --, --, --, --, --, --],
[-87.60663406256548, --, --, --, --, --, --],
[-87.59210358472923, --, --, --, --, --, --],
[-87.62592114179975, --, --, --, --, --, --],
[-87.71816696431299, --, --, --, --, --, --],
[-87.6565763901438, --, --, --, --, --, --],
[-87.64863900594533, --, --, --, --, --, --],
[-87.64907619265722, --, --, --, --, --, --],
[-87.69539301998199, --, --, --, --, --, --],
[-87.60919371688361, --, --, --, --, --, --],
[-87.64676773058504, --, --, --, --, --, --],
[-87.61508257726894, --, --, --, --, --, --],
[-87.61109823582429, --, --, --, --, --, --],
[-87.60794901995541, --, --, --, --, --, --],
[-87.66069859146353, --, --, --, --, --, --],
[-87.6446851348852, --, --, --, --, --, --],
[-87.64438008141994, --, --, --, --, --, --],
[-87.63347281118922, --, --, --, --, --, --],
[-87.64716591424734, --, --, --, --, --, --],
[-87.65677825277427, --, --, --, --, --, --],
[-87.65703560508626, --, --, --, --, --, --],
[-87.63102881317302, --, --, --, --, --, --],
[-87.54420184515567, --, --, --, --, --, --],
[-87.64399093900948, --, --, --, --, --, --],
[-87.63153167004569, --, --, --, --, --, --],
[-87.65729258714634, --, --, --, --, --, --],
[-87.6736296226221, --, --, --, --, --, --],
[-87.64647514696313, --, --, --, --, --, --],
[-87.5670347436087, --, --, --, --, --, --],
[-87.63445542054468, --, --, --, --, --, --],
[-87.64666649778596, --, --, --, --, --, --],
[-87.6353988580254, --, --, --, --, --, --],
[-87.69208330758644, --, --, --, --, --, --],
[-87.67987472541603, --, --, --, --, --, --],
[-87.6288880473052, --, --, --, --, --, --],
[-87.63133498484497, --, --, --, --, --, --],
[-87.56911419280497, --, --, --, --, --, --],
[-87.65713893195229, --, --, --, --, --, --],
[-87.63982575795488, --, --, --, --, --, --],
[-87.64968309800122, --, --, --, --, --, --],
[-87.66627785087064, --, --, --, --, --, --],
[-87.60768991764432, --, --, --, --, --, --],
[-87.63986340460846, --, --, --, --, --, --],
[-87.63017721238154, --, --, --, --, --, --],
[-87.64271285534649, --, --, --, --, --, --],
[-87.63692635382557, --, --, --, --, --, --],
[-87.68840658206535, --, --, --, --, --, --],
[-87.68639424460982, --, --, --, --, --, --],
[-87.67971630848649, --, --, --, --, --, --],
[-87.68134923819026, --, --, --, --, --, --],
[-87.6652102372879, --, --, --, --, --, --],
[-87.63905032174591, --, --, --, --, --, --],
[-87.69822984437612, --, --, --, --, --, --],
[-87.70758832634793, --, --, --, --, --, --],
[-87.60824261786335, --, --, --, --, --, --],
[-87.68502518903846, --, --, --, --, --, --],
[-87.67666348420444, --, --, --, --, --, --],
[-87.65184998823406, --, --, --, --, --, --],
[-87.65576943439689, --, --, --, --, --, --],
[-87.67502226068834, --, --, --, --, --, --],
[-87.67495423682854, --, --, --, --, --, --],
[-87.77024768348971, --, --, --, --, --, --],
[-87.76474227896196, --, --, --, --, --, --],
[-87.67440580109745, --, --, --, --, --, --],
[-87.62062959129157, --, --, --, --, --, --],
[-87.6192656193883, --, --, --, --, --, --],
[-87.67955436986004, --, --, --, --, --, --],
[-87.65761633777541, --, --, --, --, --, --],
[-87.54792339554031, --, --, --, --, --, --],
[-87.75194652296219, --, --, --, --, --, --],
[-87.6964643882578, --, --, --, --, --, --],
[-87.64773169995742, --, --, --, --, --, --],
[-87.70701265034963, --, --, --, --, --, --],
[-87.6631859770511, --, --, --, --, --, --],
[-87.66325805923087, --, --, --, --, --, --],
[-87.68273844008236, --, --, --, --, --, --],
[-87.71189753652736, --, --, --, --, --, --],
[-87.64385660800737, --, --, --, --, --, --],
[-87.62861981584953, --, --, --, --, --, --],
[-87.65582427736987, --, --, --, --, --, --],
[-87.64399888515813, --, --, --, --, --, --],
[-87.75517298463835, --, --, --, --, --, --],
[-87.76290638279215, --, --, --, --, --, --],
[-87.71399913924206, --, --, --, --, --, --]],
mask=[[False, True, True, ..., True, True, True],
[False, True, True, ..., True, True, True],
[False, True, True, ..., True, True, True],
...,
[False, True, True, ..., True, True, True],
[False, True, True, ..., True, True, True],
[False, True, True, ..., True, True, True]],
fill_value=1e+20) though perhaps we don't like NumPy masked arrays (the equivalent of Awkward's option-type, when applied to numbers). Padding is often paired with ak.fill_none, which replaces missing values with a given value. >>> ak.fill_none(ak.pad_none(ak.mean(longitude, axis=-1), 7, clip=True), 0)
<Array [[-87.8, 0, 0, 0, 0, ... 0, 0, 0, 0, 0]] type='1061 * 7 * float64'> Now we could use ak.to_numpy or even plain np.asarray to get a NumPy array. Some libraries automatically coerce their arguments into NumPy arrays (in which case, you don't need to np.asarray explicitly), but some don't. >>> np.asarray(ak.fill_none(ak.pad_none(ak.mean(longitude, axis=-1), 7, clip=True), 0))
array([[-87.7898291 , 0. , 0. , ..., 0. ,
0. , 0. ],
[-87.7485014 , 0. , 0. , ..., 0. ,
0. , 0. ],
[-87.61668302, 0. , 0. , ..., 0. ,
0. , 0. ],
...,
[-87.75517298, 0. , 0. , ..., 0. ,
0. , 0. ],
[-87.76290638, 0. , 0. , ..., 0. ,
0. , 0. ],
[-87.71399914, 0. , 0. , ..., 0. ,
0. , 0. ]]) I hope this is enough to get you started! |
Beta Was this translation helpful? Give feedback.
-
First, hats off for a fantastic package! Now I'm still very new to it, and while trying to apply it especially to GeoJSON data I wonder if there is some recommended way I haven't discovered yet to flatten/reduce/search/collect (many terms seem to apply) to a nested tree into a flat list, in my case for example GeoJSON
features
or evengeometry
fields which can exist on multiple levels, depending on the general structure and feature type (e.g. Polygon vs MultiPolygon). I've looked at https://awkward-array.org/how-to-math-reducing.html?highlight=reduce, but it's empty. Any pointers are much welcome!Beta Was this translation helpful? Give feedback.
All reactions