WordPress Ajax Filter

In the way you are using wp_localize_script(), the object’s name is filters, not reports; so, in filter.js you should use filters.ajax_filter. Also, you should define the variable options before use it.

$( document ).ready(function() {
  $("input:checkbox").on( "change", function() {
        console.log($('input[name="filter[]"]:checked').serialize());
        jQuery.ajax({
            url : filters.ajax_filter,
            type : 'post',
            data : {
                action : 'filter_reports',
                // You should define options var before use it
                // filter : options
            },
            success : function( response ) {
                alert(response)
            }
        });
  });
});

I suggest you to use more explicit names for the variables; choose names that explain themselves; of course that is just a opinion. For example:

// Use the name of the script as handle parameter
wp_enqueue_script( 'filter', plugins_url( '/js/filter.js', __FILE__ ), array('jquery'), '1.0', true );

// Use a name for the object which explain that it is data for filter script
wp_localize_script( 'filter', 'filter_data',
          array(
              // Use a nanme that explain what the property contains
              'ajax_url' => admin_url( 'admin-ajax.php' ),
          )
);

Then, in filter.js you must use filter_data.ajax_url:

$( document ).ready(function() {
  $("input:checkbox").on( "change", function() {
        console.log($('input[name="filter[]"]:checked').serialize());
        jQuery.ajax({
            url : filter_data.ajax_url,
            type : 'post',
            data : {
                action : 'filter_reports',
                // You should define options var before use it
                // filter : options
            },
            success : function( response ) {
                alert(response)
            }
        });
  });
});