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

Scan parallel lists rows, cols, vals in lock-step. For each triple, create the inner dict for a new row key when it first appears, then store the value at grid[r][c]. The grid grows key-by-key as we process each triple.

naive.py
Replay: real traced execution (multi-file project)
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)
  1. rows ← ['a', 'a', 'b', 'b', 'c', 'c']

    1rows = ['a', 'a', 'b', 'b', 'c', 'c']2cols = ['x', 'y', 'x', 'y', 'x', 'y']
    values this step['a', 'a', 'b', 'b', 'c', 'c']rows
  2. cols ← ['x', 'y', 'x', 'y', 'x', 'y']

    1rows = ['a', 'a', 'b', 'b', 'c', 'c']2cols = ['x', 'y', 'x', 'y', 'x', 'y']3vals = [1, 2, 3, 4, 5, 6]
    values this step['x', 'y', 'x', 'y', 'x', 'y']cols
  3. vals ← [1, 2, 3, 4, 5, 6]

    2cols = ['x', 'y', 'x', 'y', 'x', 'y']3vals = [1, 2, 3, 4, 5, 6]4grid = {}
    values this step[1, 2, 3, 4, 5, 6]vals
  4. grid ← {}

    3vals = [1, 2, 3, 4, 5, 6]4grid = {}5for i in range(len(rows)):
    values this step{}grid
  5. i ← 0

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
    values this step0i
  6. r ← 'a'

    5for i in range(len(rows)):6    r = rows[i]7    c = cols[i]
    values this step'a'r
  7. c ← 'x'

    6r = rows[i]7c = cols[i]8v = vals[i]
    values this step'x'c
  8. v ← 1

    7c = cols[i]8v = vals[i]9if r not in grid:
    values this step1v
  9. if r not in grid:

    8v = vals[i]9if r not in grid:10    grid[r] = {}
  10. grid ← {'a': {}}

    9if r not in grid:10    grid[r] = {}11grid[r][c] = v
    values this step{} {'a': {}}grid
  11. grid ← {'a': {'x': 1}}

    10        grid[r] = {}11    grid[r][c] = v12print('RESULT:', grid)
    values this step{'a': {}} {'a': {'x': 1}}grid
  12. i ← 1

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
    values this step0 1i
  13. r = rows[i]

    5for i in range(len(rows)):6    r = rows[i]7    c = cols[i]
  14. c ← 'y'

    6r = rows[i]7c = cols[i]8v = vals[i]
    values this step'x' 'y'c
  15. v ← 2

    7c = cols[i]8v = vals[i]9if r not in grid:
    values this step1 2v
  16. if r not in grid:

    8v = vals[i]9if r not in grid:10    grid[r] = {}
  17. grid ← {'a': {'x': 1, 'y': 2}}

    10        grid[r] = {}11    grid[r][c] = v12print('RESULT:', grid)
    values this step{'a': {'x': 1}} {'a': {'x': 1, 'y': 2}}grid
  18. i ← 2

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
    values this step1 2i
  19. r ← 'b'

    5for i in range(len(rows)):6    r = rows[i]7    c = cols[i]
    values this step'a' 'b'r
  20. c ← 'x'

    6r = rows[i]7c = cols[i]8v = vals[i]
    values this step'y' 'x'c
  21. v ← 3

    7c = cols[i]8v = vals[i]9if r not in grid:
    values this step2 3v
  22. if r not in grid:

    8v = vals[i]9if r not in grid:10    grid[r] = {}
  23. grid ← {'a': {'x': 1, 'y': 2}, 'b': {}}

    9if r not in grid:10    grid[r] = {}11grid[r][c] = v
    values this step{'a': {'x': 1, 'y': 2}} {'a': {'x': 1, 'y': 2}, 'b': {}}grid
  24. grid ← {'a': {'x': 1, 'y': 2}, 'b': {'x': 3}}

    10        grid[r] = {}11    grid[r][c] = v12print('RESULT:', grid)
    values this step{'a': {'x': 1, 'y': 2}, 'b': {}} {'a': {'x': 1, 'y': 2}, 'b': {'x': 3}}grid
  25. i ← 3

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
    values this step2 3i
  26. r = rows[i]

    5for i in range(len(rows)):6    r = rows[i]7    c = cols[i]
  27. c ← 'y'

    6r = rows[i]7c = cols[i]8v = vals[i]
    values this step'x' 'y'c
  28. v ← 4

    7c = cols[i]8v = vals[i]9if r not in grid:
    values this step3 4v
  29. if r not in grid:

    8v = vals[i]9if r not in grid:10    grid[r] = {}
  30. grid ← {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}}

    10        grid[r] = {}11    grid[r][c] = v12print('RESULT:', grid)
    values this step{'a': {'x': 1, 'y': 2}, 'b': {'x': 3}} {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}}grid
  31. i ← 4

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
    values this step3 4i
  32. r ← 'c'

    5for i in range(len(rows)):6    r = rows[i]7    c = cols[i]
    values this step'b' 'c'r
  33. c ← 'x'

    6r = rows[i]7c = cols[i]8v = vals[i]
    values this step'y' 'x'c
  34. v ← 5

    7c = cols[i]8v = vals[i]9if r not in grid:
    values this step4 5v
  35. if r not in grid:

    8v = vals[i]9if r not in grid:10    grid[r] = {}
  36. grid ← {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {}}

    9if r not in grid:10    grid[r] = {}11grid[r][c] = v
    values this step{'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}} {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {}}grid
  37. grid ← {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5}}

    10        grid[r] = {}11    grid[r][c] = v12print('RESULT:', grid)
    values this step{'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {}} {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5}}grid
  38. i ← 5

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
    values this step4 5i
  39. r = rows[i]

    5for i in range(len(rows)):6    r = rows[i]7    c = cols[i]
  40. c ← 'y'

    6r = rows[i]7c = cols[i]8v = vals[i]
    values this step'x' 'y'c
  41. v ← 6

    7c = cols[i]8v = vals[i]9if r not in grid:
    values this step5 6v
  42. if r not in grid:

    8v = vals[i]9if r not in grid:10    grid[r] = {}
  43. grid ← {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5, 'y': 6}}

    10        grid[r] = {}11    grid[r][c] = v12print('RESULT:', grid)
    values this step{'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5}} {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5, 'y': 6}}grid
  44. for i in range(len(rows)):

    4grid = {}5for i in range(len(rows)):6    r = rows[i]
  45. stdout ← RESULT: {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5, 'y': 6}}

    11    grid[r][c] = v12print('RESULT:', grid)
    values this stepRESULT: {'a': {'x': 1, 'y': 2}, 'b': {'x': 3, 'y': 4}, 'c': {'x': 5, 'y': 6}}stdout

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.

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.