20

I have a layer in QGIS, and I want to duplicate it through a plugin so I can use the copy of it as I want, without modifying the original.

Of course layer2 = layer1 will not work, because everything that happens to layer2 will also happen to layer1, as it is the same object behind all this.

The only way I found to do it is as such:

QgsVectorFileWriter.writeAsVectorFormat(layer1, r"C:\Users\ABC\AppData\Local\Temp\NewLayer.shp", "utf-8", None, "ESRI Shapefile") layer2 = QgsVectorLayer("C:\Users\ABC\AppData\Local\Temp\NewLayer.shp", "New vector", "ogr") #do something with layer2 

Is there a simple way to duplicate the layer in memory, without having to write a new file?

3 Answers 3

24

In QGIS 3 you can make a copy of a layer without saving any reference to the parent layer in this way:

# imports import processing from qgis.utils import iface from qgis.core import QgsProject # choose a layer layer = iface.activeLayer() layer.selectAll() clone_layer = processing.run("native:saveselectedfeatures", {'INPUT': layer, 'OUTPUT': 'memory:'})['OUTPUT'] layer.removeSelection() QgsProject.instance().addMapLayer(clone_layer) 

The QgsVectorLayer class has a clone() method that allows you to clone the layer in a new layer, the problem is that if you modify the geometry in the cloned layer the original layer will be affected: the reason for this is that the data source is the same for the original layer and the cloned layer.

0
20

The following code works for me from both the Python Console and plugin. It takes the features from the source input layer and copies the attributes to a memory layer (in this case, a polygon layer but you can change it to LineString or Point depending on layer type):

# imports from qgis.utils import iface from qgis.core import QgsVectorLayer, QgsMapLayerRegistry layer = QgsVectorLayer("path/to/layer", "polygon", "ogr") feats = [feat for feat in layer.getFeatures()] mem_layer = QgsVectorLayer("Polygon?crs=epsg:4326", "duplicated_layer", "memory") mem_layer_data = mem_layer.dataProvider() attr = layer.dataProvider().fields().toList() mem_layer_data.addAttributes(attr) mem_layer.updateFields() mem_layer_data.addFeatures(feats) QgsMapLayerRegistry.instance().addMapLayer(mem_layer) 
0
8

Since QGIS 3.0, there is another approach available. Use the materialize() method from the QgsFeatureSource class.

Over the entire layer with the allFeatureIds() method:

# imports from qgis.utils import iface from qgis.core import QgsFeatureRequest, QgsProject # choose a layer layer = iface.activeLayer() # or with: layer = QgsProject.instance().mapLayersByName('LAYER_NAME')[0] # create a new layer from all features new_layer = layer.materialize(QgsFeatureRequest().setFilterFids(layer.allFeatureIds())) # add a new layer to the map QgsProject.instance().addMapLayer(new_layer) 

Over the selection of all features with the selectedFeatureIds() method from the QgsVectorLayer class:

# imports from qgis.utils import iface from qgis.core import QgsFeatureRequest, QgsProject # choose a layer layer = iface.activeLayer() # or with: # or with: layer = QgsProject.instance().mapLayersByName('LAYER_NAME')[0] # select all features in the original layer layer.selectAll() # create a new layer from selected features new_layer = layer.materialize(QgsFeatureRequest().setFilterFids(layer.selectedFeatureIds())) # remove selection in the original layer layer.removeSelection() # add a new layer to the map QgsProject.instance().addMapLayer(new_layer) 

References:

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.