Create a collection of pages from a structure field

groupBy() is a method of the collection object. In your case, you will be dealing with an array of dates, however, so no groupBy(), and you don’t need it. Once you have your array of dates, loop through it and then for each of the dates use a function that collects all the events that belong to that date (then loop through the collection of results). Within that methods, you will have to make a distinction between pages with a single event and pages with multiple events (don’t know if you are using different templates or a toggle field?).

Get array of all dates from all events (with structure field):

// in your controller
$events = page('events')->children()->visible();
foreach($events as $event) {
  $dates = $event->dates()->toStructure()->pluck('date', ',');
  foreach($dates as $date) {
    $dates[] = $date;
  }
}

$dates = array_unique($dates, SORT_NUMERIC);

To get all events per day from events with a structure field of dates, you can use a function like this:

// put this into your controller or into a plugin file
function getEventsPerDate($events, $date) {

  $eventsPerDay = $events->filter(function($child) use($date) {
    $dates = $child->dates()->toStructure()->pluck('date', ',');
    // check if the current day is in dates
    if(in_array($date, $dates)) {
      return $child;
    }
  });
 
  return $eventsPerDay;

}

In your template:

<?php

foreach($dates as $date) {
  // you don't need to define events again, if it is already defined in your controller
  // just putting it here to make it clearer
  $events = page('events')->children()->visible();
  $dayEvents = getEventsPerDate($events, $date);
  foreach($dayEvents as $event) {
    echo $event->title(); 
  }
}