diff --git a/common/util/math.ts b/common/util/math.ts index a255c19f..a89b31e1 100644 --- a/common/util/math.ts +++ b/common/util/math.ts @@ -1,3 +1,5 @@ +import { sortBy } from 'lodash' + export const logInterpolation = (min: number, max: number, value: number) => { if (value <= min) return 0 if (value >= max) return 1 @@ -16,4 +18,15 @@ export function normpdf(x: number, mean = 0, variance = 1) { ) } -const TAU = Math.PI * 2 +export const TAU = Math.PI * 2 + +export function median(values: number[]) { + if (values.length === 0) return NaN + + const sorted = sortBy(values, (x) => x) + const mid = Math.floor(sorted.length / 2) + if (sorted.length % 2 === 0) { + return (sorted[mid - 1] + sorted[mid]) / 2 + } + return sorted[mid] +} diff --git a/web/pages/stats.tsx b/web/pages/stats.tsx index c73b6821..e7590e98 100644 --- a/web/pages/stats.tsx +++ b/web/pages/stats.tsx @@ -157,13 +157,11 @@ export async function getStaticPropz() { bets?.map((b) => b.userId) ?? [], comments?.map((c) => c.userId) ?? [] ) - const counts = Object.entries(countBy(userIds)) - const topTenth = sortBy(counts, ([, count]) => count) - .reverse() - // Take the top 10% of users, except for the top 2, to avoid outliers. - .slice(2, counts.length * 0.1) - const topTenthTotal = sumBy(topTenth, ([_, count]) => count) - return topTenthTotal + const counts = Object.values(countBy(userIds)) + const sortedCounts = sortBy(counts, (count) => count).reverse() + if (sortedCounts.length === 0) return 0 + const tenthPercentile = sortedCounts[Math.floor(sortedCounts.length * 0.1)] + return tenthPercentile }) const weeklyTopTenthActions = dailyTopTenthActions.map((_, i) => { const start = Math.max(0, i - 6) @@ -212,9 +210,11 @@ export async function getStaticPropz() { weekOnWeekRetention, weeklyActivationRate, monthlyRetention, - dailyTopTenthActions, - weeklyTopTenthActions, - monthlyTopTenthActions, + topTenthActions: { + daily: dailyTopTenthActions, + weekly: weeklyTopTenthActions, + monthly: monthlyTopTenthActions, + }, manaBet: { daily: dailyManaBet, weekly: weeklyManaBet, @@ -237,9 +237,11 @@ export default function Analytics(props: { weekOnWeekRetention: number[] monthlyRetention: number[] weeklyActivationRate: number[] - dailyTopTenthActions: number[] - weeklyTopTenthActions: number[] - monthlyTopTenthActions: number[] + topTenthActions: { + daily: number[] + weekly: number[] + monthly: number[] + } manaBet: { daily: number[] weekly: number[] @@ -258,9 +260,11 @@ export default function Analytics(props: { weekOnWeekRetention: [], monthlyRetention: [], weeklyActivationRate: [], - dailyTopTenthActions: [], - weeklyTopTenthActions: [], - monthlyTopTenthActions: [], + topTenthActions: { + daily: [], + weekly: [], + monthly: [], + }, manaBet: { daily: [], weekly: [], @@ -301,9 +305,11 @@ export function CustomAnalytics(props: { weekOnWeekRetention: number[] monthlyRetention: number[] weeklyActivationRate: number[] - dailyTopTenthActions: number[] - weeklyTopTenthActions: number[] - monthlyTopTenthActions: number[] + topTenthActions: { + daily: number[] + weekly: number[] + monthly: number[] + } manaBet: { daily: number[] weekly: number[] @@ -321,9 +327,7 @@ export function CustomAnalytics(props: { weekOnWeekRetention, monthlyRetention, weeklyActivationRate, - dailyTopTenthActions, - weeklyTopTenthActions, - monthlyTopTenthActions, + topTenthActions, manaBet, } = props @@ -525,10 +529,10 @@ export function CustomAnalytics(props: { /> - + <Title text="Action count of top tenth" /> <p className="text-gray-500"> - From the top 10% of users, how many bets, comments, and markets did they - create? (Excluding top 2 users each day.) + Number of actions (bets, comments, markets created) taken by the tenth + percentile of top users. </p> <Tabs defaultIndex={1} @@ -537,7 +541,7 @@ export function CustomAnalytics(props: { title: 'Daily', content: ( <DailyCountChart - dailyCounts={dailyTopTenthActions} + dailyCounts={topTenthActions.daily} startDate={startDate} small /> @@ -547,7 +551,7 @@ export function CustomAnalytics(props: { title: 'Weekly', content: ( <DailyCountChart - dailyCounts={weeklyTopTenthActions} + dailyCounts={topTenthActions.weekly} startDate={startDate} small /> @@ -557,7 +561,7 @@ export function CustomAnalytics(props: { title: 'Monthly', content: ( <DailyCountChart - dailyCounts={monthlyTopTenthActions} + dailyCounts={topTenthActions.monthly} startDate={startDate} small />