hook_form_alter() to put multiple radios in a table
I think you can define a wrapper element as type table. The core user permissions form does this, and I think is similar to what you're trying to build:

 $form['permissions'] = [
  '#type' =&gt; 'table',
  '#header' =&gt; [
    $this-&gt;t('Permission'),
  ],
  '#id' =&gt; 'permissions',
  '#attributes' =&gt; [
    'class' =&gt; [
      'permissions',
      'js-permissions',
    ],
  ],
  '#sticky' =&gt; TRUE,
];
foreach ($role_names as $name) {
  $form['permissions']['#header'][] = [
    'data' =&gt; $name,
    'class' =&gt; [
      'checkbox',
    ],
  ];


In your case, I think you'd define something like $form['sow'] as a '#type' =&gt; 'table' which will be a wrapper element that all the checkbox (or radios) appear under.

Then loop through your fields (these will be similar to how the user permission form loops through each permission, creating a row).

foreach ($fields as $low) {
  $form['sow'][$low]['description'] = [
    '#type' =&gt; 'item',
    '#title' =&gt; $low['title'],
    '#description' =&gt; ...,
  ];

  // Now loop through each assignment. This will be similar
  // to how the user permission form loops through each role
  // for each permission.
  foreach ($assignments as $assignment) {
    $form['sow'][$low][$assignment] = [
      '#type' =&gt; 'checkbox', // Or 'radio', depending on the need.
      // Other form element details here too.
    ];
  }


Then, for each assignment (these will behave similar to each role in the user permission form)