====== Feature count ======
Suppose you have two vectors: one that contains points associated with surveyed sites, and another made of areas that represent fields or different regions of survey. You want to know how many sites are in each area and draw a map that brings this information.
If your sites are classified into different types or classes (based on period or size), you might want also to know what distribution different classes have for each of your survey areas.
===== With GRASS =====
This is a shell script for **GRASS** that calls ''v.what.vect'' to know which points fall
into each area. Counts for each area are written to a new column
"count". This attribute can be used as input for d.vect.chart (bar
chart).
You can you also provide a column name for the points vector, that
contains a classification attribute. This way more columns are created,
to be used for creating pie-charts. When you use pie-charts, the "count"
column can be used to generate different sizes of graphics proportional
to the total number of points in each area.
This script is quite slow. If someone with enough skills (not me) wants to
write a better module, I think significant parts of code from ''v.qcount''
can be useful. It would be good to have such a feature included by
default in GRASS, with an efficient and fast code.
To run the script, cd into the directory that contains the script from the GRASS prompt and call it (it's useful to ''chmod 755 v.count.points.sh'').
#!/bin/sh
#
############################################################################
#
# MODULE: v.count.points
#
# AUTHOR(S): Stefano Costa steko@iosa.it
#
# PURPOSE: generate summary statistics for point features
# COPYRIGHT: (C) 2007 by the GRASS Development Team
#
# This program is free software under the GNU General Public
# License (>=v2). Read the file COPYING that comes with GRASS
# for details.
#
##
#############################################################################
#
#
#%Module
#% description: count the number of point features from vector A that are within areas from vector B
#%End
#%option
#% key: points
#% type: string
#% gisprompt: old,vector,vector
#% description: points vector to be counted for each area
#% required : yes
#%end
#%option
#% key: polygon
#% type: string
#% description: polygon vector
#% gisprompt: old,vector,vector
#% required : yes
#%end
#%option
#% key: output
#% type: string
#% description: output layer
#% required : yes
#%end
#%option
#% key: classescol
#% type: string
#% description: column that contains classification for points
#% required : no
#%end
if [ -z "$GISBASE" ] ; then
echo "You must be in GRASS GIS to run this program."
exit 1
fi
if [ "$1" != "@ARGS_PARSED@" ] ; then
exec g.parser "$0" "$@"
fi
### setup enviro vars ###
eval `g.gisenv`
: ${GISBASE?} ${GISDBASE?} ${LOCATION_NAME?} ${MAPSET?}
LOCATION=$GISDBASE/$LOCATION_NAME/$MAPSET
points=$GIS_OPT_points
polygon=$GIS_OPT_polygon
output=$GIS_OPT_output
tempsql=`g.tempfile pid=$$`
# overwrites the output map if it already exists
g.copy vect=$points,temppnts,$polygon,$output --o
if [ -n "$GIS_OPT_classescol" ]; then
classescol=$GIS_OPT_classescol
echo "Using classes!"
classes=$(db.select -c temppnts sql="select $classescol from temppnts" | uniq)
for j in $classes; do
v.db.addcol $output col="class_$j int"
done
fi
v.db.addcol temppnts col="cat_area int"
v.db.addcol $output col="count int"
v.what.vect vector=temppnts qvect=$output column=cat_area qcolumn=cat
areas=$(db.select -c $output sql="select cat from $output" | uniq)
for i in $areas; do
count=$( db.select -c temppnts sql="select cat_area from temppnts" | grep -c "^$i$")
echo "UPDATE $output SET count = $count WHERE cat = $i;" >> $tempsql
if [ -n "$GIS_OPT_classescol" ]; then
for j in $classes; do
kount=$( db.select -c temppnts sql="select $classescol from temppnts where cat_area = $i" | grep -c "^$j$")
echo "UPDATE $output SET class_$j = $kount WHERE cat = $i;" >> $tempsql
done
fi
done
cat $tempsql | db.execute
g.remove vect=temppnts
echo "Output written to map $output"
Here are some result maps made with ''d.vect.chart'':
{{spatial_analysis:countpoints-bars.jpg?300|Barcharts with d.vect.chart based on the output of the script}} {{spatial_analysis:countpoints-pies.jpg?300|Piecharts with d.vect.chart based on the output of the script}}
===== With PostGIS =====
Flavio Rigolon [[http://www.faunalia.com/pipermail/gfoss/2007-August/005360.html|suggested]] this approach using [[http://www.postgis.org|PostGIS]]:
dbname => CREATE TABLE new_table AS SELECT grid.cat, COUNT(id) AS count FROM points,grid WHERE points.the_geom && grid.the_geom AND CONTAINS (grid.the_geom,points.the_geom) GROUP BY grid.cat;
You should obtain a table. You can then JOIN ''new_table'' to your ''grid'' table using the ''cat'' column.