## Is your feature request related to a problem?

#4947 added a new query to the backend – time to convert. It works well, just one point is kind of rough: bin width and count.

## Describe the solution you'd like

Currently the number of bins is hardcoded. Ideally we should have two options:
- return a user-specified number of bins,
- otherwise infer a reasonable number of bins using some algorithm (auto option).

@alexkim205 [suggested](https://github.com/PostHog/posthog/issues/4855#issuecomment-872423877) the [Freedman-Diaconis rule](https://en.wikipedia.org/wiki/Freedman%E2%80%93Diaconis_rule) for determining bin width (and interval based on that), but unfortunately from my testing its formula would not be the most practical – it's great for keeping a pretty constant "smoothness" of the histogram esp. with normal distribution, but we face some additional constraints that make it less than ideal:
- we can't have histograms too dense visually in the UI, from my testing a practical limit is 60 bins (above that it gets too dense),
- our data generally doesn't follow much of a normal distribution.

Clamping may help though, or maybe a different formula may work better outright – I'll be testing this.

## Additional context

Issue pertaining to the experience of time to convert: #4855

#### *Thank you* for your feature request – we love each and every one!

posthog/models/filters/mixins/common.py
events = json.loads(events)
            _entities.extend([Entity({**entity, "type": TREND_FILTER_TYPE_EVENTS}) for entity in events])
        return sorted(_entities, key=lambda entity: entity.order if entity.order else -1)
    @cached_property
    def actions(self) -> List[Entity]:
        return [entity for entity in self.entities if entity.type == TREND_FILTER_TYPE_ACTIONS]
    @cached_property
    def events(self) -> List[Entity]:
        return [entity for entity in self.entities if entity.type == TREND_FILTER_TYPE_EVENTS]
    @include_dict
    def entities_to_dict(self):
        return {
            **({"events": [entity.to_dict() for entity in self.events]} if len(self.events) > 0 else {}),
            **({"actions": [entity.to_dict() for entity in self.actions]} if len(self.actions) > 0 else {}),
        }
class EntityIdMixin(BaseParamMixin):
    @cached_property
    def target_entity_id(self) -> Optional[str]:
        return self._data.get("entityId", None) or self._data.get("entity_id", None)
    @include_dict
    def entity_id_to_dict(self):
        return {"entity_id": self.target_entity_id} if self.target_entity_id else {}
class EntityTypeMixin(BaseParamMixin):
    @cached_property
    def target_entity_type(self) -> Optional[str]:
        return self._data.get("type", None) or self._data.get("entity_type", None)
    @include_dict
    def entity_type_to_dict(self):
        return {"entity_type": self.target_entity_type} if self.target_entity_type else {}