MCPcopy Create free account
hub / github.com/Openpanel-dev/openpanel / processCohortData

Function processCohortData

packages/db/src/services/retention.service.ts:447–504  ·  view source on GitHub ↗
(
  data: Array<{
    cohort_interval: string;
    total_first_event_count: number;
    [key: string]: number | string;
  }>,
  diffInterval: number,
  interval: IRetentionInterval = 'day',
  until?: string
)

Source from the content-addressed store, hash-verified

445// the row is internally consistent: period 0 equals Total profiles and the
446// curve starts at 100%.
447export function processCohortData(
448 data: Array<{
449 cohort_interval: string;
450 total_first_event_count: number;
451 [key: string]: number | string;
452 }>,
453 diffInterval: number,
454 interval: IRetentionInterval = 'day',
455 until?: string
456): IRetentionCohortRow[] {
457 if (data.length === 0) {
458 return [];
459 }
460
461 const columns = range(0, diffInterval + 1);
462 const processed = data.map((row) => {
463 const sum = row.total_first_event_count;
464 const values = columns.map(
465 (index) => (row[`interval_${index}_user_count`] || 0) as number
466 );
467
468 return {
469 cohort_interval: row.cohort_interval,
470 sum,
471 values,
472 percentages: values.map((value) => (sum > 0 ? round(value / sum, 2) : 0)),
473 };
474 });
475
476 const maturePeriods = processed.map((row) =>
477 maturePeriodCount(row.cohort_interval, until, interval)
478 );
479 const totalSize = processed.reduce((acc, row) => acc + row.sum, 0);
480 const representativeSize = round(totalSize / processed.length, 0);
481
482 const averageRow: IRetentionCohortRow = {
483 cohort_interval: 'Weighted Average',
484 sum: representativeSize,
485 values: [],
486 percentages: [],
487 };
488
489 for (const index of columns) {
490 let matureSize = 0;
491 let retained = 0;
492 processed.forEach((row, i) => {
493 if (index <= maturePeriods[i]!) {
494 matureSize += row.sum;
495 retained += row.values[index]!;
496 }
497 });
498 const rate = matureSize > 0 ? retained / matureSize : 0;
499 averageRow.percentages.push(round(rate, 2));
500 averageRow.values.push(round(rate * representativeSize, 0));
501 }
502
503 return [averageRow, ...processed];
504}

Callers 2

getRetentionCohortFunction · 0.85

Calls 4

roundFunction · 0.90
maturePeriodCountFunction · 0.85
mapMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected