v.dissolve(1)

v.dissolve πŸ’…

okay bestie, welcome to v.dissolve(1) from the GRASS GIS User's Manual β€” she's a vector module and she's about to merge everything that's giving the same energy. adjacent? overlapping? same category? same attribute? say less, she's fusing them. 🫢


✨ NAME ✨

v.dissolve β€” dissolves adjacent or overlaping features sharing a common category number or attribute.

yes, "overlaping" β€” that's the original spelling, i'm not touching it, it's iconic and it's canon πŸ’€

🏷️ KEYWORDS 🏷️

vector, dissolve, area, line


🌸 SYNOPSIS 🌸

v.dissolve
v.dissolve --help
v.dissolve input=name  [layer=string]   [column=name]  output=name
[aggregate_columns=name[,name,...]]
[aggregate_methods=string[,string,...]]
[result_columns=name[,name,...]]   [aggregate_backend=string]
[--overwrite]  [--help]  [--verbose]  [--quiet]  [--ui]

πŸŽ€ Flags πŸŽ€

  • --overwrite β€” let the output files overwrite existing files. yes she will bulldoze, that's the vibe, be careful bestie 😭
  • --help β€” prints the usage summary, the little cheat sheet, the crib notes πŸ’–
  • --verbose β€” verbose module output, she's gonna talk more
  • --quiet β€” quiet module output, she's gonna shut up (respect)
  • --ui β€” force launching the GUI dialog, if you're a clicky girlie πŸ–±οΈβœ¨

πŸ’œ Parameters πŸ’œ

  • input=name [required] β€” the name of the input vector map. Or, plot twist, a data source for direct OGR access.
  • layer=string β€” layer number or name. vector features can have category values in different layers, and this number determines which layer to use. when it's used with direct OGR access, this is the layer name. default: 1
  • column=name β€” name of attribute column used to dissolve features
  • output=name [required] β€” name for the output vector map 🌈
  • aggregate_columns=name[,name,...] β€” names of attribute columns to get aggregate statistics for. one column name or SQL expression per method if result columns are specified.
  • aggregate_methods=string[,string,...] β€” aggregate statistics method (e.g., sum). the default is all available basic statistics for a given backend (for sql backend: avg, count, max, min, sum)
  • result_columns=name[,name,...] β€” new attribute column names for aggregate statistics results. defaults to the aggregate column name and statistics name and can contain type.
  • aggregate_backend=string β€” backend for attribute aggregation. default is sql unless the provided aggregate methods are for univar. options: sql, univar
    • sql: Uses SQL attribute database
    • univar: Uses v.db.univar

πŸ‘‘ DESCRIPTION πŸ‘‘

The v.dissolve module is used to merge adjacent or overlapping features in a vector map that share the same category value. The resulting merged feature(s) retain this category value. periodt. πŸ’…

Figure: Areas with the same attribute value (first image) are merged into one (second image).

So instead of dissolving features based on category values, you can define an integer or string column using the column parameter. in that case, features that share the same value in that column get dissolved. but heads up bestie: the newly created layer does not retain the category (cat) values from the input layer. it's giving fresh start, no baggage. πŸ¦‹

also, note that multiple areas with the same category or the same attribute value that are not adjacent get merged into one entity, which consists of multiple features, i.e., a multipart feature. yeah, she's a multipart girlie, main character energy fr fr.


🧚 Attribute aggregation 🧚

The attributes of merged areas can be aggregated using various aggregation methods, and the specific methods available depend on the backend used for aggregation. two aggregate backends (specified with the aggregate_backend parameter) are available: univar and sql. the backend is determined automatically based on the requested methods β€” when the function is one of the SQL build-in aggregate functions, the sql backend is used. Otherwise, the univar backend is used. it's giving auto-detect, no cap.

The default behavior is intended for interactive use and testing. but for scripting and other automated usage, explicitly specifying the backend with the aggregate_backend parameter is strongly recommended. and when you're choosing: note that the sql aggregate backend, regardless of the underlying database, will typically perform significantly better than the univar backend. so like, sql ate and left no crumbs πŸ”₯


🌸 Aggregation using univar backend 🌸

When univar is used, the methods available are the ones which v.db.univar uses by default, i.e., n, min, max, range, mean, mean_abs, variance, stddev, coef_var, and sum. that's the whole squad, she's not gatekeeping.


⭐ Aggregation using sql backend ⭐

When the sql backend is used, the methods depend on the SQL database backend used for the attribute table of the input vector. For SQLite, there are at least the following built-in aggregate functions: count, min, max, avg, sum, and total. For PostgreSQL, the list of aggregate functions is much longer and includes, e.g., count, min, max, avg, sum, stddev, and variance. postgres really said "i contain multitudes" πŸ™ˆ


πŸ’– Defining the aggregation method πŸ’–

If only the parameter aggregate_columns is provided, all the following aggregation statistics are calculated: n, min, max, mean, and sum. If the univar backend is specified, all the available methods for the univar backend are used. the way she just does the whole set without being asked, so generous πŸ₯Ή

The aggregate_methods parameter can be used to specify which aggregation statistics should be computed. Alternatively, the parameter aggregate_columns can be used to specify the method using SQL syntax. This provides the highest flexibility, and it is suitable for scripting. The SQL statement should specify both the column and the functions applied, e.g.,

aggregate_columns="sum(cows) / sum(animals)"

Note that when the aggregate_columns parameter is used, the sql backend should be used. In addition, the aggregate_columns and aggregate_methods cannot be used together. 🚫 (they are NOT a collab, do not try to make them a collab)

For convenience, certain methods, namely n, count, mean, and avg, are automatically converted to the appropriate name for the selected backend. However, for scripting, it is recommended to specify the appropriate method (function) name for the backend, as the conversion is a heuristic that may change in the future. so like, cute for now, but don't build your whole life on it bestie πŸ’€

If the result_columns is not provided, each method is applied to each column specified by aggregate_columns. This results in a column for each of the combinations. These result columns have auto-generated names based on the aggregate column and method. For example, setting the following parameters:

aggregate_columns=A,B
aggregate_methods=sum,n

results in the following columns: A_sum, A_n, B_sum, B_n. See the Examples section. she's making combos, she's a matchmaker πŸ’…

If the result_column is provided, each method is applied only once to the matching column in the aggregate column list, and the result will be available under the name of the matching result column. For example, setting the following parameter:

aggregate_columns=A,B
aggregate_methods=sum,max
result_column=sum_a, n_b

results in the column sum_a with the sum of the values of A and the column n_b with the max of B. Note that the number of items in aggregate_columns, aggregate_methods (unless omitted), and result_column needs to match, and no combinations are created on the fly. See the Examples section. so like β€” one-to-one, no surprises, no spontaneous ships. ✨

For scripting, it is recommended to specify all resulting column names, while for interactive use, automatically created combinations are expected to be beneficial, especially for exploratory analysis.

The type of the result column is determined based on the method selected. For n and count, the type is INTEGER and for all other methods, it is DOUBLE. Aggregate methods that produce other types require the type to be specified as part of the result_columns. A type can be provided in result_columns using the SQL syntax name type, e.g., sum_of_values double precision. Type specification is mandatory when SQL syntax is used in aggregate_columns (and aggregate_methods is omitted). so yeah, don't skip the type, she will notice πŸ™ˆ


πŸ“ NOTES πŸ“

GRASS defines a vector area as a composite entity consisting of a set of closed boundaries and a centroid. The centroids must contain a category number (see v.centroids), this number is linked to area attributes and database links. it's a whole ecosystem, iykyk 🌈

Multiple attributes may be linked to a single vector entity through numbered fields referred to as layers. Refer to v.category for more details.

Merging of areas can also be accomplished using v.extract -d which provides some additional options. In fact, v.dissolve is simply a front-end to that module. The use of the column parameter adds a call to v.reclass before. plot twist: she's been standing on someone's shoulders this whole time πŸ˜­πŸ’–

Basic use πŸ’…

Okay bestie, the absolute simplest glow-up ever, no thoughts head empty:

v.dissolve input=undissolved output=dissolved

That's it. That's the post. ✨

Dissolving based on column attributes 🌸

Say you wanna merge by a column instead. The North Carolina data set, iconic as always:

g.copy vect=soils_general,mysoils_general
v.dissolve mysoils_general output=mysoils_general_families column=GSL_NAME

Dissolving adjacent SHAPE files to remove tile boundaries 🧩

So if the tile boundaries of adjacent maps (think CORINE Landcover SHAPE files) gotta go, you need an extra step to nuke the duplicated boundaries. It's giving extra credit but we do it anyway:

# patch tiles after import:
v.patch -e `g.list type=vector pat="clc2000_*" separator=","` out=clc2000_patched
# remove duplicated tile boundaries:
v.clean clc2000_patched out=clc2000_clean tool=snap,break,rmdupl thresh=.01
# dissolve based on column attributes:
v.dissolve input=clc2000_clean output=clc2000_final col=CODE_00

Attribute aggregation πŸŽ€

Now the fun part. While dissolving, we can also aggregate the attribute values of the original features. So let's aggregate area in acres (ACRES) of all the municipal boundaries (boundary_municp) in the full NC dataset, while dissolving common boundaries based on the name in the DOTURBAN_N column. (Long lines get split with a backslash, marking a continued line just like in Bash β€” very slay of us):

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities \
    aggregate_columns=ACRES

To peep the result, we use v.db.select, grabbing only one row for DOTURBAN_N == ’Wadesboro’:

v.db.select municipalities where="DOTURBAN_N == ’Wadesboro’" separator=tab

The resulting table may look like this:

cat  DOTURBAN_N    ACRES_n    ACRES_min    ACRES_max    ACRES_mean    ACRES_sum
66   Wadesboro     2          634.987      3935.325     2285.156      4570.312

See how that made multiple columns for each of the statistics computed by default? A lot, I know. We can limit how many stats get computed by specifying the method we want:

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities_2 \
    aggregate_columns=ACRES aggregate_methods=sum

And that gives you a single column with the sum for all values in the ACRES column, for each group of original features that had the same value in DOTURBAN_N and are now dissolved (merged) into one. Chef's kiss. πŸ‘‘

Aggregating multiple attributes 🌈

Expanding on the previous example, we can compute values for multiple columns at once by adding more columns to the aggregate_columns option. Let's compute the average of values in the NEW_PERC_G column:

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities_3 \
    aggregate_columns=ACRES,NEW_PERC_G aggregate_methods=sum,avg

By default, all the methods specified in aggregate_methods get applied to all the columns, so the result of the above is four columns. Which is lowkey convenient when you want multiple statistics for similar columns (like averages and standard deviations of several population statistics columns). But in our case each column is different, and each aggregate method should only be applied to its corresponding column.

So here's the tea: v.dissolve will apply each aggregate method only to the corresponding column when the column names for the results are specified manually with the result_columns option:

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities_4 \
    aggregate_columns=ACRES,NEW_PERC_G aggregate_methods=sum,avg \
    result_columns=acres,new_perc_g

Now we have full control over what columns get created 🫢 β€” but we also have to specify an aggregate method for each column, even when the aggregate methods are the same:

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities_5 \
    aggregate_columns=ACRES,DOTURBAN_N,TEXT_NAME aggregate_methods=sum,count,count \
    result_columns=acres,number_of_parts,named_parts

Now, for interactive exploratory analysis it's often not necessary to specify aggregate methods or names. But for scripting, specifying both aggregate_methods and result_columns manually is best practice β€” unless you're using SQL syntax for aggregate_columns, in which case, see below, bestie. πŸ‘‡

Aggregating using SQL syntax πŸ’€

The aggregation can also be done using the full SQL syntax and the set of aggregate functions available for a given attribute database backend. Here we'll assume the default SQLite database backend for attribute.

Modifying the previous example, we'll now specify the SQL aggregate function calls explicitly instead of letting v.dissolve generate them for us. We'll compute the sum of the ACRES column using sum(ACRES) β€” or alternatively, we could use SQLite specific total(ACRES), which returns zero even when all values are NULL, iykyk. Next we'll count the number of aggregated (i.e., dissolved) parts using count(*), which counts all rows regardless of NULL values. Then we'll count all unique names of parts as distinguished by the MB_NAME column using count(distinct MB_NAME). And finally we'll collect all these names into a comma-separated list using group_concat(MB_NAME):

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities_6 \
    aggregate_columns="total(ACRES),count(*),count(distinct MB_NAME),group_concat(MB_NAME)" \
    result_columns="acres REAL,named_parts INTEGER,unique_names INTEGER,names TEXT"

Here v.dissolve doesn't make any assumptions about the resulting column types, so we specified both the name and the type of each column.

When working with general SQL syntax, v.dissolve turns off its checks for the number of aggregate and result columns, so that all SQL syntax can be used for aggregate columns. That means we can also use functions with multiple parameters β€” for example, specifying the separator to be used with group_concat:

v.dissolve input=boundary_municp column=DOTURBAN_N output=municipalities_7 \
    aggregate_columns="group_concat(MB_NAME, ’;’)" \
    result_columns="names TEXT"

To inspect the result, we'll use v.db.select, retrieving only one row for DOTURBAN_N == ’Wadesboro’:

v.db.select municipalities_7 where="DOTURBAN_N == ’Wadesboro’" separator=tab

The resulting table may look like this:

cat  DOTURBAN_N     names
66   Wadesboro Wadesboro;Lilesville

πŸ” SEE ALSO πŸ”

  • v.category, v.centroids, v.extract, v.reclass, v.db.univar, v.db.select

πŸ‘‘ AUTHORS πŸ‘‘

  • M. Hamish Bowman, Department of Marine Science, Otago University, New Zealand (module)
  • Markus Neteler (column support)
  • Trevor Wiens (help page)
  • Vaclav Petras, NC State University, Center for Geospatial Analytics, GeoForAll Lab (aggregate statistics)

πŸ’– SOURCE CODE πŸ’–

Available at: v.dissolve source code (history)

Accessed: Saturday Jan 17 05:41:53 2026

Main index | Vector index | Topics index | Keywords index | Graphical index | Full index

Β© 2003-2025 GRASS Development Team, GRASS GIS 8.4.2 Reference Manual


And that's a wrap on v.dissolve(1), bestie β€” straight from the GRASS 8.4.2 Reference Manual, dated Saturday Jan 17 05:41:53 2026. πŸ¦‹βœ¨ Go dissolve some polygons, you ate. Periodt. πŸ’…

πŸ“¦ where this page comes from