Fold long-form rows (row_key, col_key, value) into a nested dict-of-dicts, filling each cell from the matching triple. With pandas, pivot_table does this in one call and handles duplicate cells via an aggregation function.

By hand

With pandas

df.pivot_table(index='r', columns='c', values='v') reshapes the long DataFrame into a wide one. The snapshot shows the row index, the column labels, and per-column value lists.

naive.py
rows = ['a', 'a', 'b', 'b', 'c', 'c']
cols = ['x', 'y', 'x', 'y', 'x', 'y']
vals = [1, 2, 3, 4, 5, 6]
grid = {}
for i in range(len(rows)):
    r = rows[i]
    c = cols[i]
    v = vals[i]
    if r not in grid:
        grid[r] = {}
    grid[r][c] = v
print('RESULT:', grid)
library.py
import pandas as pd
from dalib.display import set_display
set_display()

rows = ['a', 'a', 'b', 'b', 'c', 'c']
cols = ['x', 'y', 'x', 'y', 'x', 'y']
vals = [1, 2, 3, 4, 5, 6]
df = pd.DataFrame({'r': rows, 'c': cols, 'v': vals})
pt = df.pivot_table(index='r', columns='c', values='v')
result = {r: {c: int(pt.loc[r, c]) for c in pt.columns} for r in pt.index}
print('index:', pt.index.tolist())
print('columns:', pt.columns.tolist())
print('x:', [int(pt.loc[r, 'x']) for r in pt.index])
print('y:', [int(pt.loc[r, 'y']) for r in pt.index])
print('RESULT:', result)
index: ['a', 'b', 'c']
columns: ['x', 'y']
x: [1, 3, 5]
y: [2, 4, 6]
RESULT: {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5, 'y': 6}}

Implementation notes

  • pivot_table defaults to aggfunc='mean'. With unique (index, columns) pairs (no duplicate cells), mean of a single value is that value — the result matches the original. Pass aggfunc='sum' or aggfunc='count' to aggregate duplicate cells instead.
  • Cells with no matching row in the long data become NaN. Supply fill_value=0 (or another sentinel) to replace them.
  • The result dtype is float64 by default (mean returns float). Cast with int() after confirming no NaN cells.
  • Cross-reference: pivot-long-to-wide (python-data-basics) for the pure-Python nested-dict version; melt-wide-to-long (this chapter) for the inverse operation.