Welcome to our tutorial on using Python with QGIS! QGIS is a powerful open-source geographic information system (GIS) that supports various GIS operations and spatial data management. One of the fantastic features of QGIS is its built-in Python console, which allows you to enhance your GIS projects with programming.
QGIS brings a Python API (see PyQGIS Developer Cookbook for some code samples) to let the user interact with its objects (layers, features, or interface). QGIS also has a Python console.
Using Python in QGIS allows you to automate repetitive tasks, manipulate spatial data in ways that are cumbersome or impossible with the GUI alone, and extend the functionality of QGIS through custom scripts and plugins.
Throughout this tutorial, we will explore simple Python commands and scripts that you can execute in the Python console to interact with QGIS and perform basic GIS operations. These activities are designed to be fun and engaging, providing you with a hands-on introduction to programming within a GIS environment.
Let’s get started with some basic commands to familiarize you with the Python console in QGIS!
QGIS extends Python’s capabilities by providing a specialized module called qgis
. This module allows you to interact with the QGIS application, manipulating geographical data and automating tasks.
To start scripting with Python in QGIS, you'll first need to import the necessary modules provided by QGIS. These typically include:
qgis.core
: Provides core functionality like managing and manipulating vector and raster layers.qgis.utils
: Contains utility functions for interacting with the QGIS interface.iface
: A special variable from the qgis.utils
module representing the QGIS interface, allowing you to interact with the application itself, like opening and displaying layers.Here’s how to import these modules into your QGIS Python script:
from qgis.core import *
import qgis.utils
With these imports, you’re now ready to use the QGIS Python API to enhance your GIS projects with automated scripts and customized functionality!
In this part of our tutorial, we'll learn how to read a GeoJSON file that contains various crop types, subset the data for rice crops, and then write the results to a new file. We will also explore a variant where you'll learn to write the results to a Shapefile instead by reading the QGIS API documentation.
First, we need to load our GeoJSON file into QGIS. We'll use the iface
object, which is a part of the QGIS Python API that represents the main interface of QGIS.
from qgis.core import *
import qgis.utils
# Path to the GeoJSON file
# NOTE: Please make sure 'r' is in front of the path
file_path = r'path_to_your_file/tz_labels.geojson'
# Load the layer in
all_crops = iface.addVectorLayer(file_path, # path to the file
baseName= "All Crops", # name of the layer in QGIS
providerKey="ogr") # how to read it
if not all_crops:
print("Layer failed to load!")
else:
print("Layer loaded successfully!")
Paste these lines into the Python console in QGIS to see the output and press
You should now see Rice Crops
in your QGIS Layers Panel. This layer contains the crop types data from the GeoJSON file.
From this point on we will be refering this layer by the name all_crops
in our code.
Where do I find the path to my file?
In order to load a file into python you will need to find the 'path' to the tz_labels.geojson
file. Start by Layer
> Add Layer
> Add Vector Layer
. Then in your layers list right-click
on tz_labels
and select Properties
. In the General
tab you will find the Layer Source
which is the path to your file. Copy and paste this path into the file_path
variable in the code above.
Make sure your path doesn't include 'file://'
at the beginning.
Next, we'll filter out the rice crops from our dataset. We'll assume that the crop types are stored in a field named crop_type
.
# Select features where the crop type is 'Rice'
all_crops.selectByExpression("\"primary_crop\" = 'maize'")
# Print the number of selected rows
print(f"Number of selected rows: {all_crops.selectedFeatureCount()}")
Paste these lines into the Python console in QGIS to see the output and press
Note:
For more on how to create expressions in Qgis see Select Expressions
After subsetting the data, let's write the selected features to a new GeoJSON file.
# Define the output file path
output_path = r'path_to_output/rice_subset.geojson'
# Write the selected features to a new GeoJSON
error = QgsVectorFileWriter.writeAsVectorFormat(layer = all_crops,
fileName = output_path, # path and name of the output file
fileEncoding = "UTF-8", # encoding of the output file
destCRS = all_crops.crs(), # projection of the output file
driverName ="GeoJSON", # output file format
onlySelected=True) # write only selected features
if error[0] == QgsVectorFileWriter.NoError:
print("Success: GeoJSON file has been created.")
else:
print("Error: Failed to write GeoJSON.")
Your output_path
should be a new file in the same directory as the original file. You can now load this new file into QGIS to see the subset of rice crops.
Please follow the following link to the full script for this tutorial.
Now that you've created a new GeoJSON file with the subset of rice crops, try loading it into QGIS and exploring the data using output_path
and iface.addVectorLayer()
If you want to write the output to a Shapefile instead, you'll need to consult the QGIS API documentation to learn about the parameters required for writing a Shapefile. Here's how you might start:
QgsVectorFileWriter
and read about the different parameters you can use, especially how to specify the output format for a Shapefile.Here’s a hint on how you might adjust the code for writing a Shapefile:
# Define the output file path for the Shapefile
output_path_shp = r'path_to_output/rice_subset.shp'
error = QgsVectorFileWriter.writeAsVectorFormat(layer = all_crops,
fileName = output_path_shp, # path and name of the output file
fileEncoding = "UTF-8", # encoding of the output file
destCRS = all_crops.crs(), # projection of the output file
driverName = __________________, # output file format
onlySelected=True) # write only selected features
if error_shp[0] == QgsVectorFileWriter.NoError:
print("Success: Shapefile has been created.")
else:
print("Error: Failed to write Shapefile.")
In this tutorial, we learned how to use Python in QGIS to read a GeoJSON file, subset the data for rice crops, and write the results to a new file. We also explored how to write the output to a Shapefile by consulting the QGIS API documentation.
In this tutorial, we will learn how to load a vector layer into QGIS, access its attribute data, and perform a basic analysis by counting the number of observations for each crop type using the primary_crop
field from the tz_labels.geojson
dataset.
First, let’s load the tz_labels.geojson
into QGIS. Open the Python console in QGIS and use the following command to add the layer:
# Load the tz_labels.geojson file
file_path = r"/path/to/tz_labels.geojson" # Update this path to your file's location
tz_labels_layer = iface.addVectorLayer(file_path, "TZ Labels", "ogr")
if not tz_labels_layer:
print("Failed to load the layer.")
else:
print("Layer loaded successfully.")
In Python, a dictionary is a collection of key-value pairs where each key is unique. This structure is ideal for counting occurrences of items because you can use the item as the key and its count as the value.
Let’s look at a simple example using a list of fruits to illustrate how we can use a dictionary to count occurrences.
# List of fruits
fruits = ['apple', 'banana', 'orange', 'apple', 'orange', 'banana', 'orange']
fruit_counts
where each fruit name will be a key, and the count of that fruit will be the corresponding value.# Initialize a dictionary to hold the count of each fruit
fruit_counts = {}
Iterate Through the List: We loop through each element in the fruits
list.
Update the Dictionary: As we move through the elements of fruits
list, we update the fruit_counts
dictionary:
if fruit in fruit_counts
), we increase its count by 1.fruit
key in the dictionary, we add it and set its count to 1.# Iterate over the list of fruits
for fruit in fruits:
if fruit in fruit_counts:
fruit_counts[fruit] += 1 # Increment the count if the fruit is already in the dictionary
else:
fruit_counts[fruit] = 1 # Set the count to 1 if the fruit is not in the dictionary yet
items()
method returns a list of tuple pairs (key, value) from the dictionary.# Print the counts for each fruit
for fruit, count in fruit_counts.items():
print(f"{fruit}: {count}")
Output:
The following is the output of the code snippet above:
apple: 2
banana: 2
orange: 3
We can apply the same technique to count crop types from a feature layer in QGIS. Here’s how it connects to our GIS data example:
# Initialize a dictionary to hold the count of each crop type
crop_counts = {}
# Access the features (rows) in the layer
for feature in tz_labels_layer.getFeatures():
# Get the value of the 'primary_crop' field
crop_type = feature['primary_crop']
# Use the dictionary counting method
if crop_type in crop_counts:
crop_counts[crop_type] += 1
else:
crop_counts[crop_type] = 1
# Print the counts for each crop type
for crop, count in crop_counts.items():
print(f"{crop}: {count}")
Your output should be as follows:
maize: 403
rice: 280
soybeans: 10
sunflower: 278
peanuts: 13
fallow_barren: 1
cassava: 76
sorghum: 131
okra: 2
millet: 139
no: 5
cotton: 50
don_t_know: 2
large_building: 1
forest_shrubland: 2
could be maize.: 1
water_body: 1
water: 5
This method efficiently tracks the number of occurrences of each crop type, providing a quick summary of the data in your GIS layer. By leveraging Python dictionaries, you can easily extend this approach to count various attributes across different datasets in QGIS.
Please follow the following link to the full script for this tutorial.
Our tz_labels.geojson
dataset contains a field named field_size
that represents the size of each field. Try adapting the code to count the number of observations for each field size category.
This tutorial demonstrates a simple way to perform attribute data analysis directly within QGIS using Python. By counting the occurrences of different crop types, we can quickly assess the composition of agricultural data in the provided tz_labels.geojson
. This process can be adapted to other datasets and attributes for various analytical needs.
PLEASE CLEAR THE CONSOLE BEFORE MOVING ON TO THE NEXT TUTORIAL
Press the following button to clear the console:
In this tutorial, we will learn how to load a polygon vector layer into QGIS, access its geometrical data, and calculate the total area of the polygons in acres. We will use the sa_labels.geojson
dataset and focus on the field named 'crop_name'.
First, let's load the sa_labels.geojson
file into your QGIS project. Make sure to open the Python Console within QGIS to run these commands:
# Path to the sa_labels.geojson file
layer_path = r"/path/to/sa_labels.geojson" # Change this to the actual file path
# Load the layer into QGIS
sa_labels_layer = iface.addVectorLayer(layer_path, "SA Labels", "ogr")
if not sa_labels_layer:
print("Failed to load the layer.")
else:
print("Layer loaded successfully.")
When working with geographic data, understanding the coordinate reference system (CRS) and its linear units is crucial because the measurement of areas, lengths, and other spatial calculations depends on these units.
In QGIS, each projected layer has a CRS, which defines how the two-dimensional, flat map in QGIS relates to real places on the earth. The CRS includes the type of projection and the units used for the linear measurements, which could be meters, feet, or any other units.
These units are important as they directly affect how measurements like area and distance are calculated and interpreted.
To determine the linear unit of the projection for a layer in QGIS, you can inspect the layer’s CRS. Here’s how you can do this using the Python console in QGIS:
# Assuming 'sa_labels_layer' is the layer you've loaded
crs = sa_labels_layer.crs()
# Print the CRS description
print(f"Unit name: {crs.description()}")
# Print the Proj4 string with linear unit
print(f"Proj4 description: {crs.toProj()}")
Here the Proj4 string will contain the linear unit of the projection. For example, if the unit is in meters, you will see +units=m
in the Proj4 string.
Once the layer is loaded, we can calculate the total area of the polygons. Since the area will be calculated in the layer's coordinate reference system units, we need to convert these units to acres. The conversion factor from square meters to acres is approximately 0.000247105.
In order to calculate the total area in acres, we will iterate through each feature in the layer, retrieve its geometry, and sum the areas (measured in ) of the polygons in a variable called total_area_sqm
.
Here's how you can do this in QGIS Python:
# Initialize a variable to hold the total area in square meters
total_area_sqm = 0
# Iterate through each feature in the layer
for feature in sa_labels_layer.getFeatures():
# Get the geometry of the feature
geom = feature.geometry()
# Add the area of the geometry to the total area
total_area_sqm += geom.area()
# Convert square meters to acres (1 square meter = 0.000247105 acres)
total_area_acres = total_area_sqm * 0.000247105
# Print the total area in acres
print(f"Total area of crops: {total_area_acres:.2f} acres")
Please follow the following link to the full script for this tutorial.
Extend the code to calculate the total area of each crop type in the sa_labels.geojson
dataset. You can use a dictionary to store the total area for each crop type.
Let me help you get started, here is a snippet of code that you can use to calculate the total area of each crop type:
# Initialize a dictionary to hold the total area for each crop type
area_by_crop = {}
# Iterate through each feature in the layer
for feature in sa_labels_layer.getFeatures():
crop_type = feature['crop_name'] # Adjust the field name if different
area_sqm = feature.geometry().area() # Area in the CRS's units (e.g., square meters)
# Convert the area to acres
# your code
# Update the area_by_crop dictionary for the crop type
# your code
# Print the total area for each crop type
for crop, area in area_by_crop.items():
print(f"{crop}: {area:.2f} acres")
This tutorial provides you with a basic understanding of how to work with polygon geometries in QGIS using Python, specifically focusing on calculating areas and converting these areas into different units. Such skills are valuable for a wide range of GIS and environmental analysis tasks.
The answers to the challenge questions can be found in the Challenge Solutions page.
The basics of python tutorial can be found here