[GRASS-dev] Write array to (point) attribute table

Moritz Lennert mlennert at club.worldonline.be
Thu Oct 1 00:15:44 PDT 2015


On 01/10/15 00:05, Paulo van Breugel wrote:
>
>
> On 30-09-15 17:52, Paulo van Breugel wrote:
>>
>>
>> On 30-09-15 17:47, Anna Petrášová wrote:
>>>
>>>
>>> On Wed, Sep 30, 2015 at 11:20 AM, Paulo van Breugel
>>> <p.vanbreugel at gmail.com> wrote:
>>>
>>>
>>>
>>>     On 30-09-15 16:18, Anna Petrášová wrote:
>>>>
>>>>
>>>>     On Wed, Sep 30, 2015 at 9:27 AM, Paulo van Breugel
>>>>     <p.vanbreugel at gmail.com <mailto:p.vanbreugel at gmail.com>> wrote:
>>>>
>>>>
>>>>
>>>>         On Wed, Sep 30, 2015 at 11:53 AM, Pietro
>>>>         <peter.zamb at gmail.com> wrote:
>>>>
>>>>             On Wed, Sep 30, 2015 at 9:51 AM, Paulo van Breugel
>>>>             <p.vanbreugel at gmail.com> wrote:
>>>>             >
>>>>             >
>>>>             > On Wed, Sep 30, 2015 at 2:02 AM, Anna Petrášová
>>>>             <kratochanna at gmail.com>
>>>>             > wrote:
>>>>             >>
>>>>             >>
>>>>             >>
>>>>             >> On Tue, Sep 29, 2015 at 6:09 PM, Paulo van Breugel
>>>>             >> <p.vanbreugel at gmail.com> wrote:
>>>>             >>>
>>>>             >>> This must be a very basic question, but I can't find
>>>>             an easy/direct way
>>>>             >>> to do this. In python, if I have an array with
>>>>             values with a length equal to
>>>>             >>> the number of rows in an attribute table of a
>>>>             (point) vector layer, how can
>>>>             >>> I write those values to a new column in that
>>>>             attribute table. I can of
>>>>             >>> course first create the column, but than how to
>>>>             update that column with the
>>>>             >>> values in the array?
>>>>             >>
>>>>             >>
>>>>             >> it should be pretty easy to do with pygrass,
>>>>             unfortunately there is no
>>>>             >> example on assigning attributes in the official
>>>>             documentation [1], but it
>>>>             >> should be pretty easy, something like that (not tested):
>>>>             >>
>>>>             >> with VectorTopo('myvector', mode='w') as vectormap:
>>>>             >>     for feature in vectormap:
>>>>             >>  feature.attrs['mycolumn'] = value
>>>>             >>
>>>>             >>
>>>>             > Thanks, but that seems to write the vector back
>>>>             without attribute table
>>>>
>>>>             You have to save the changes in the database out from
>>>>             your cycle, with:
>>>>
>>>>             vectormap.table.conn.commit()
>>>>
>>>>
>>>>         Thanks Pietro. I am, however, not sure I understand (I tried
>>>>         to use it, but thanks to my limited experience in Python /
>>>>         pygrass not much luck). Just to be more specific, I am
>>>>         trying to create a script that divides points in training
>>>>         and test groups, similar to v.kcv, but with points clustered
>>>>         in space. E.g.,
>>>>
>>>>         # Create vector
>>>>         grass.run_command("v.random", output="testB", npoints=10,
>>>>         overwrite=True)
>>>>         grass.run_command("v.db.addtable", map="testB", columns="X
>>>>         DOUBLE PRECISION,Y DOUBLE PRECISION,GR INTEGER")
>>>>         grass.run_command("v.to.db", map="test", option="coor",
>>>>         columns="X,Y")
>>>>
>>>>         # Create groups
>>>>         vectmap = 'test'
>>>>         cvals = array(grass.vector_db_select(vectmap, layer =
>>>>         int(1), columns = 'X,Y')['values'].values()).astype(np.float)
>>>>         centroids,_ = kmeans(cvals,2)
>>>>         idx,_ = vq(cvals,centroids)
>>>>
>>>>         # write results to tabel
>>>>         Now I would like to write idx to the column 'GR' in the
>>>>         attribute table of 'test'.
>>>>
>>>>         p.s. I am first creating the XY columns now, but is there a
>>>>         function to get the coordinates (cvals) in pygrass directly?
>>>>
>>>>
>>>>     I don't fully understand the example,
>>>
>>>     Thanks for the quick response. I basically have a list with
>>>     values (idx in the example above) which I like to add as a column
>>>     to the attribute table of an existing vector (point layer). The
>>>     length of idx is equal to the number of rows in the attribute
>>>     table. The solution of Anna seems like an elegant solution (and
>>>     easier and more flexible than other solutions I tried using e.g.,
>>>     sqlite3). However, as I wrote, I end up with a vector without
>>>     attribute table. You wrote that I "have to save the changes in
>>>     the database out from your cycle, with:
>>>     vectormap.table.conn.commit()". I am, however, not sure what you
>>>     mean with 'out from your cycle' or how to implement that.
>>>
>>>
>>> probably after the for cycle ends you would call this
>>> 'vectormap.table.conn.commit()', if it doesn't works, try to put it
>>> in the cycle (I am not sure what is supposed to work).
>>
>> I did try both, with no luck so-far. I'll give it another try though,
>> perhaps I did something else wrong.
>
> Tried out again, but after running the code below, I end up with an
> empty vector layer (no points and no attribute table). Same if I put the
> vectormap.table.conn.commit() in the for cycle.
>
> import grass.script as grass
>
> from grass.pygrass.vector import VectorTopo
>
> grass.run_command("v.random", output="testB", npoints=10, overwrite=True)
>
> grass.run_command("v.db.addtable", map="testB", columns="GR INTEGER")
>
> with VectorTopo('testB', mode='w') as vectormap:
>
>      for feature in vectormap:
>
>          feature.attrs['GR'] = 9
>
>          vectormap.table.conn.commit()


Just a wild guess, here without looking at the library code, but could 
it be that it should be

VectorTopo('testB', mode='a')

instead of

VectorTopo('testB', mode='w')

Moritz


More information about the grass-dev mailing list