Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Python for Demographic and Market Data Analysis

Hello! Welcome back.

In our last lesson, we constructed a weighted scoring model to bring structure and objectivity to the complex process of comparing investment properties. We saw how criteria related to the market, the property itself, and the deal could be weighted and scored to produce a final, comparable number. A key part of that model relies on assessing market factors like population trends and economic strength.

Today, we transition from theory to practice and tackle the "how" of gathering that market data. This lesson's outcome is to write a Python script to fetch and analyze demographic and market data for a specific area using a public API. As a software engineer, you'll find this topic very familiar. We're essentially going to build the data pipelines that feed the "Market" section of the scoring model we just designed, making your analysis repeatable, scalable, and data-driven.

To start, let's consider why we need this data. Long-term demographic trends are a fundamental driver of real estate value. A growing population increases demand for housing, while a declining one can lead to stagnation.

Projected Relative Change of Population in European NUTS 3 Regions (2019-2050)
This map from Eurostat illustrates projected population changes across European regions until 2050. Areas in red are projected to grow, while areas in blue are projected to shrink. An investor would clearly favor regions with strong growth prospects. Our goal today is to learn how to acquire this type of data programmatically.

1. The API Workflow: From Request to DataFrame

An Application Programming Interface (API) is a standard way for different software applications to communicate. Many data providers, from government statistics agencies to real estate portals, offer APIs that allow us to request and receive data in a structured format, most commonly JSON.

There are generally two ways to interact with an API in Python:

  1. Using a Wrapper Library: A developer creates a Python package that handles the complexities of authentication and request formatting, giving you simple functions to call (e.g., get_population_data('Madrid')).
  2. Direct HTTP Requests: You use a library like requests to manually construct and send HTTP requests and then parse the raw JSON response yourself.

We'll start by learning the process with a wrapper library, as it's often the most efficient method.

Economic Data Analysis Project with Python Pandas - Data scraping, cleaning and exploration!

The video 'Economic Data Analysis Project with Python Pandas' by Rob Mulla provides an excellent, comprehensive walkthrough of the entire process using the FRED (Federal Reserve Economic Data) API. While the data is US-centric, the workflow is universal. We will use it to learn the core steps of using a data API.

Please watch the following segments to understand the end-to-end process: Setup and API Key (00:00 - 04:14): Focus on how he installs the fredapi library and sets up the API key. This is the initial authentication step. Searching and Fetching Data (06:11 - 13:05): Pay close attention to how he first searches for the data series ID (fred.search()) and then uses that ID to retrieve the actual time-series data (fred.get_series()). This search-then-fetch pattern is very common. Combining Multiple Series (13:05 - 24:00): Observe the technique of looping through multiple series IDs, fetching each one, and then concatenating them into a single Pandas DataFrame. This is crucial for comparing different regions or metrics.

The key workflow you saw in the video can be summarized as:

  1. Authentication: Obtain an API key and instantiate the API client object.
  2. Discover: Search for the specific data series you need to find their unique IDs.
  3. Fetch: Request the data for one or more series IDs.
  4. Process: Load the data into a Pandas DataFrame for cleaning, analysis, and visualization.

2. A Spanish Example: Demographic Data from INE

Now, let's apply that exact workflow to a Spanish data source. The equivalent of FRED in Spain is the Instituto Nacional de Estadística (INE), the official source for demographic and economic data.

Fortunately, there's a Python wrapper library for the INE's 2021 Census API, making our job much easier.

sigdeletras/censosine21

The GitHub repository for the censosine21 library provides the documentation we need to get started. It's a wrapper for the INE's Population and Housing Census 2021 API.

Please review the following sections of the README.md file: Read the main description to understand the library's purpose. Look at the Installation section for the pip command. Review the Kick off section to see how to instantiate the CensosINE21 object and use the .post() method. This is the core data fetching mechanism. Skim the Show API entities info section, which is analogous to the fred.search() method for discovering what data is available. Note the mention of the /examples directory, which is an excellent resource for more complex queries.

Let's put this into practice. Say we want to get the total population for the provinces of Madrid and Barcelona to feed into our scoring model. Based on the censosine21 documentation, the process is straightforward.

First, install the library:
pip install censosine21

Now, we can write a script to fetch the population data. After exploring the available tables (using the static methods mentioned in the docs), we'd find that table 36321 contains population by province.

import pandas as pd
from censosine.ine import CensosINE21

# 1. Instantiate the CensosINE21 object
ine_api = CensosINE21()

# 2. Define the parameters for our request
# We want the 'Population' metric from table '36321'
# The variable 'PROV' corresponds to provinces
params = {
    'table': '36321',
    'metrics': 'Población',
    'variables': {
        'PROV': ['28 Madrid', '08 Barcelona']
    }
}

# 3. Make the request to the INE API
try:
    ine_api.post(params)
    
    # 4. The data is stored in the .data attribute as a list of dictionaries
    if ine_api.data:
        # Convert the list of dictionaries to a Pandas DataFrame
        df = pd.DataFrame(ine_api.data)
        
        # Clean up and display the data
        df_cleaned = df[['Nombre', 'Valor']]
        df_cleaned = df_cleaned.rename(columns={'Nombre': 'Province', 'Valor': 'Population'})
        
        print("2021 Population Data from INE:")
        print(df_cleaned)
    else:
        print("No data returned from the API.")

except Exception as e:
    print(f"An error occurred: {e}")

# Example Output:
# 2021 Population Data from INE:
#        Province  Population
# 0   28 Madrid     6751251
# 1  08 Barcelona     5714730

This script is a tangible tool that automates the collection of a key demographic indicator for your market analysis. You could easily expand it to pull other variables like age distribution, household size, or housing tenure, all of which are available through the INE API.

3. Direct API Interaction: Getting Property Data from Idealista

Wrapper libraries are great, but they don't exist for every API. For many services, especially commercial ones, you'll need to handle the HTTP requests and JSON parsing directly. Your software engineering background makes this a standard task.

Before diving into a real estate example, let's quickly review the core logic of handling JSON from an API response in Python.

Python Tutorial: Working with JSON Data using the json Module

Corey Schafer's tutorial 'Working with JSON Data' is a classic. We'll focus on the section where he fetches data from a public web API.

Please watch the segment from 11:45 to 17:10. The key takeaway is the process: Use a library like urllib or requests to get a response from a URL. Read the response content, which is a string. Use json.loads() to parse that string into a Python dictionary. Navigate the nested dictionary to extract the data you need.

Now, let's apply this direct-request method to the most relevant data source for us: Idealista, Spain's largest real estate portal. Idealista provides a developer API that gives access to its listings.

Note: The Idealista API requires you to register for a key. We will walk through the process using a detailed guide, and you can follow the steps to register on your own time to get your own credentials.

Calling the Idealista API using Python

The article 'Calling the Idealista API using Python' by Guilherme Datt is a perfect, practical guide. It lays out the entire process, from authentication to handling paginated results.

Read through the article to understand the complete workflow. Focus on these key code blocks: Authentication: Review the first code block showing how to combine your API key and secret, encode them, and make a POST request to the oauth/token endpoint to get an access token. Defining Parameters: Look at the second block, where he defines the search URL by concatenating parameters like country, operation, center (latitude/longitude), and distance. This is how you define your search area. Making the Call: The search_api function shows how to use the access token in an 'Authorization: Bearer' header to make the actual data request. Handling Results: The final sections show how to parse the 'elementList' from the JSON response into a DataFrame and loop through pages to get a complete dataset.

The process described in the article is a standard and powerful way to gather real-time market data. Let's summarize the key Python snippets from the article into a logical flow.

Step 1: Get Access Token (Authentication)
You send your credentials to get a temporary token.

# Simplified from the article
import requests
import base64

apikey = 'YOUR_API_KEY'
client_secret = 'YOUR_CLIENT_SECRET'

credentials = f"{apikey}:{client_secret}"
encoded_credentials = base64.b64encode(credentials.encode()).decode()

token_url = "https://api.idealista.com/oauth/token"
data = {"grant_type": "client_credentials"}
headers = {"Authorization": f"Basic {encoded_credentials}", ...}

response = requests.post(token_url, data=data, headers=headers)
token = response.json()["access_token"]

Step 2: Build Search URL and Make Request
You use the token to ask for the actual data.

# Simplified from the article
search_url = (
    "https://api.idealista.com/3.5/es/search?" +
    "operation=sale" +
    "&propertyType=homes" +
    "&center=40.4167,-3.70325" + # Madrid Center
    "&distance=5000" # 5km radius
)

headers = {'Authorization' : 'Bearer ' + token}
content = requests.post(search_url, headers=headers)
results = content.json()

# The property listings are inside the 'elementList' key
property_df = pd.DataFrame(results['elementList'])
print(property_df.head())

This property_df DataFrame would contain a wealth of information for all listings in your defined area: price, size (m²), number of rooms, location, and more. You could use this to calculate the average price per square meter in a neighborhood, analyze the distribution of property types, or identify outliers—all essential components of market analysis.

Test your understanding!

Looking at the Idealista example, imagine the property_df DataFrame contains columns named price and size. How would you add a new column price_per_sqm to this DataFrame?

Show answer

You would perform a simple element-wise division on the two columns:

property_df['price_per_sqm'] = property_df['price'] / property_df['size']

This new metric is one of the most important for comparing property values in a given market, and you've just derived it programmatically from raw API data.

Conclusion

In this lesson, you've added a powerful, practical skill to your real estate analysis toolkit. You now have the ability to go beyond static reports and programmatically fetch live market and demographic data, which is the foundation of any serious investment analysis.

Key Takeaways:

  • You can access public data using Python via wrapper libraries (like censosine21 for INE data) or through direct HTTP requests (like for the Idealista API).
  • The general workflow is to authenticate (get a key/token), build a query with your desired parameters, fetch the data, and parse the JSON response into a Pandas DataFrame.
  • With these skills, you can automate the data collection for the "Market" criteria of your scoring model, pulling fresh data on population, housing stock, and active property listings.
Python Code and Output for Real Estate Price Prediction Error Analysis
Once you have gathered comprehensive data from APIs like Idealista and INE, you can move towards more advanced applications, such as building predictive models to estimate property prices and evaluating their accuracy, as shown in this example analysis.

Preview of the Next Module:
This lesson concludes our module on Market Analysis and Due Diligence. You now have a robust framework for finding and evaluating potential deals. Our next module, "Time Value of Money and Cash Flow Projections," shifts our focus from the present state of a property to its future performance. We will begin by calculating the present and future value of cash flows, the foundational concept for modeling an investment's returns over its entire holding period.

Can't find a good explanation? Sign up and we'll make it for you

Sign up