Polars Structs: How to Pack and Unpack Multiple Columns

3D isometric illustration of a robotic assembly line packing three separate colored data columns into a single Struct crate, and unpacking a crate back into columns.

In Pandas, you are stuck with flat columns. In Polars, you can put columns inside other columns.

This is called a Struct (structure). It’s like having a Dictionary inside a DataFrame cell, but it’s strongly typed and incredibly fast.

Why use Structs?

Imagine you have x and y coordinates. Instead of managing two separate columns, you can pack them into a single point column.

1. Packing Columns (pl.struct)

import polars as pl

df = pl.DataFrame({
    "x": [1, 2, 3],
    "y": [10, 20, 30],
    "id": ["a", "b", "c"]
})

# Combine 'x' and 'y' into a 'point' struct
df_packed = df.select(
    "id",
    pl.struct(["x", "y"]).alias("point")
)
print(df_packed)

Output:

shape: (3, 2)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ id  โ”† point     โ”‚
โ”‚ --- โ”† ---       โ”‚
โ”‚ str โ”† struct[2] โ”‚
โ•žโ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ก
โ”‚ a   โ”† {1,10}    โ”‚
โ”‚ b   โ”† {2,20}    โ”‚
โ”‚ c   โ”† {3,30}    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

2. Accessing Fields (struct.field)

You can run math on the fields inside the struct without unpacking them!

# Multiply x by 2 inside the struct
df_packed.select(
    pl.col("point").struct.field("x") * 2
)

Output:

shape: (3, 1)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”
โ”‚ x   โ”‚
โ”‚ --- โ”‚
โ”‚ i64 โ”‚
โ•žโ•โ•โ•โ•โ•โ•ก
โ”‚ 2   โ”‚
โ”‚ 4   โ”‚
โ”‚ 6   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”˜

3. Unpacking (unnest)

When you’re done, you can expand them back into columns.

df_unpacked = df_packed.unnest("point")
print(df_unpacked)

Output:

shape: (3, 3)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”
โ”‚ id  โ”† x   โ”† y   โ”‚
โ”‚ --- โ”† --- โ”† --- โ”‚
โ”‚ str โ”† i64 โ”† i64 โ”‚
โ•žโ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•ก
โ”‚ a   โ”† 1   โ”† 10  โ”‚
โ”‚ b   โ”† 2   โ”† 20  โ”‚
โ”‚ c   โ”† 3   โ”† 30  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜

This is crucial for handling complex JSON data or keeping related metrics tied together during a groupby. Let’s see how this pattern handles a real-world data pipeline payload.

4. Native JSON Parsing Into Structs

Instead of using slow Python loops (json.loads) which completely drop your performance back down to row-by-row speeds, Polars can natively decode complex JSON strings straight into a typed Struct column.

import polars as pl

# Mocking a raw API response dataset
df_json = pl.DataFrame({
    "user_id": [101, 102],
    "raw_meta": [
        '{"browser": "Chrome", "os": "Linux"}', 
        '{"browser": "Safari", "os": "iOS"}'
    ]
})

# 1. Explicitly define the target schema for your JSON structure
json_schema = pl.Struct([
    pl.Field("browser", pl.String), 
    pl.Field("os", pl.String)
])

# 2. Parse natively and unnest instantly for downstream consumption
df_processed = df_json.with_columns(
    pl.col("raw_meta").str.json_decode(dtype=json_schema)
).unnest("raw_meta")

print(df_processed)

Output:

shape: (2, 3)
โ”Œโ•โ•โ•โ•โ•โ•โ•โ•โ•โ”ฌโ•โ•โ•โ•โ•โ•โ•โ•โ•โ”ฌโ•โ•โ•โ•โ•โ•โ•โ”
โ”‚ user_id โ”† browser โ”† os    โ”‚
โ”‚ ---     โ”† ---     โ”† ---   โ”‚
โ”‚ i64     โ”† str     โ”† str   โ”‚
โ•žโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•ก
โ”‚ 101     โ”† Chrome  โ”† Linux โ”‚
โ”‚ 102     โ”† Safari  โ”† iOS   โ”‚
โ””โ•โ•โ•โ•โ•โ•โ•โ•โ•โ”ดโ•โ•โ•โ•โ•โ•โ•โ•โ•โ”ดโ•โ•โ•โ•โ•โ•โ•โ”˜

Key Takeaways

  • Polars allows for packed columns called Structs, enabling complex data management within DataFrames.
  • Structs are efficient for combining related data like coordinates into a single column, enhancing performance.
  • You can access fields within a struct for calculations without unpacking, streamlining data processing.
  • Polars supports unnesting Structs, making it easy to expand data back into separate columns when needed.
  • Native JSON parsing in Polars decodes complex strings directly into Structs, improving performance over traditional methods.

Similar Posts

Leave a Reply