Overview
Two related additions on the frequency axis, plus a list-binning extension shared with the
recency axis:
frequency_mode — aggregate frequency at day granularity (distinct interaction days) in
addition to the current view granularity (interaction count). Frequency-axis counterpart of
recency_mode (v0.6.0); reuses the {day, view} vocabulary.
frequency_unit — bin the frequency value, as an int (fixed-width / periodic bins, like
recency_unit) or a list (explicit, non-periodic bin edges).
recency_unit list support — extend recency_unit to also accept a list of bin edges
(currently int only).
# Target API
RecencyFrequencyScorer(
user_col="user", item_col="item", time_col="datetime",
recency_mode="day", recency_unit=1, # int OR list (e.g. [7, 30])
frequency_mode="view", frequency_unit=1, # int OR list (e.g. [1, 3, 10]) ← NEW
)
Part 1 — frequency_mode
Terminology
| Term |
Definition |
mode |
| view freq (接触回数, current) |
Number of interaction events per (user, item) in the observation window |
frequency_mode="view" (default) |
| day freq (接触日数, new) |
Number of distinct days an item was interacted with per (user, item) |
frequency_mode="day" |
Definition
frequency_mode="view" (default): frequency = interaction count — current behavior.
frequency_mode="day": frequency = number of distinct interaction days = nunique of the day
ordinal (_SEQUENCE_COL).
Example
A user interacts with item A:
| timestamp |
item |
| 2026-06-28 17:00 |
A |
| 2026-06-28 16:00 |
A (same day) |
| 2026-06-27 10:00 |
A (previous day) |
- view freq = 3 (interaction count)
- day freq = 2 (distinct days: 06-28, 06-27)
day freq caps many same-day interactions, bounding frequency by the number of days in the
observation window. Already demonstrated via manual preprocessing in
examples/tutorial_advanced_day_freq_{en,ja}.ipynb; this makes it a first-class parameter.
Design notes
- Default must be
"view" to preserve current behavior (intentional default asymmetry vs
recency_mode="day": classic RF is time-based for recency, count-based for frequency).
- Orthogonal to
recency_mode and the high-resolution view key: day freq uses the day ordinal
(_SEQUENCE_COL), which always exists. No high-resolution key needed.
- Single-groupby swap in the
_recency.py builders: the frequency named-agg entry is
(seq_col, "count") for view, (seq_col, "nunique") for day. No extra groupby.
Part 2 — frequency_unit / recency_unit binning
Both recency_unit and frequency_unit accept an int or a list:
Int u (≥ 1): fixed-width / periodic bins
The raw metric is divided into width-u bins (1-indexed; smallest value → bin 1).
- recency:
(ref - last_view) // u + 1 (current behavior).
- frequency:
(f - 1) // u + 1 (the -1 makes f = 1 fall in bin 1).
u = 1 (default) = no extra binning.
List [e1, e2, …, ek] (ascending): explicit, non-periodic bin edges
Inclusive upper bounds; produces k + 1 bins (the last is open-ended):
value ≤ e1 → bin 1
e1 < value ≤ e2 → bin 2
- …
value > ek → bin k + 1
Example (frequency): frequency_unit=[1, 3, 10] → 1→bin 1, 2–3→bin 2, 4–10→bin 3,
11+→bin 4.
Example (recency): recency_unit=[7, 30] → 0–7 days→bin 1, 8–30→bin 2, 31+→bin 3.
Intended usage (rationale)
recency_unit is typically an int, exploiting calendar periodicity (e.g. 7 = weekly,
30 ≈ monthly).
frequency_unit is typically a list, since interaction counts are usually grouped
non-periodically (e.g. 1 vs 2–3 vs 4–10).
Design / interaction notes
frequency_unit is orthogonal to frequency_mode: it bins the resulting frequency value
whether it is view freq or day freq.
recency_unit (int or list) is ignored when recency_mode="view" (recency is a rank).
- Binning is a pure post-step on the raw value in the
_recency.py builders; no extra groupby.
Out of scope / open questions
- Exact list-edge convention (inclusive upper bound vs other) to be finalized in design; the above
is the proposed spec.
recency_mode="session" remains future and separate.
Acceptance criteria
概要
頻度(frequency) 軸に関する2つの追加と、recency 軸と共通のリストビン化拡張:
frequency_mode — 頻度を現状の view 粒度(接触回数)に加えて day 粒度(接触日数)でも
集計する。v0.6.0 の recency_mode の頻度軸版で、{day, view} 語彙を踏襲。
frequency_unit — 頻度の値をビン化する。整数(等幅・周期的ビン、recency_unit と同じ)
または リスト(非周期的な明示ビン境界)。
recency_unit のリスト対応 — recency_unit もビン境界のリストを受け付けるよう拡張(現状は
整数のみ)。
Part 1 — frequency_mode
用語整理
| 用語 |
定義 |
mode |
| view freq(接触回数, 現状) |
観測期間内の (user, item) ごとの接触イベント数 |
frequency_mode="view"(既定) |
| day freq(接触日数, 新規) |
(user, item) ごとに接触したユニーク日数 |
frequency_mode="day" |
定義
frequency_mode="view"(既定): 頻度 = 接触回数 — 現状の挙動。
frequency_mode="day": 頻度 = 接触したユニーク日数 = 日序数(_SEQUENCE_COL)の nunique。
例
あるユーザーが商品 A に接触:
| timestamp |
商品 |
| 2026-06-28 17:00 |
A |
| 2026-06-28 16:00 |
A(同日) |
| 2026-06-27 10:00 |
A(前日) |
- view freq = 3(接触回数)
- day freq = 2(ユニーク日: 06-28, 06-27)
day freq は同日内の多数の接触を抑え、頻度の上限を観測期間の日数で抑える。既に
examples/tutorial_advanced_day_freq_{en,ja}.ipynb で手動前処理として実演済みで、本 Issue は
これを正式なパラメータにする。
設計メモ
- 既定は
"view" 必須(現状挙動の保持)。recency_mode="day" との既定非対称は意図的(古典的 RF:
recency は時間ベース・frequency は回数ベース)。
recency_mode・高解像度キーと直交: day freq は日序数(_SEQUENCE_COL)から計算でき、両 recency
モードで常に存在するため高解像度キーは不要。
- 単一 groupby 切替:
_recency.py のビルダーで frequency の named-agg を (seq_col, "count")(view)
↔ (seq_col, "nunique")(day)と切り替えるだけ。groupby を増やさない。
Part 2 — frequency_unit / recency_unit のビン化
recency_unit・frequency_unit はともに 整数 または リスト を受け付ける:
整数 u(≥ 1): 等幅・周期的ビン
生の指標を幅 u の等幅ビンに分割(1 起算、最小値 → bin 1)。
- recency:
(ref - last_view) // u + 1(現状の挙動)。
- frequency:
(f - 1) // u + 1(f = 1 が bin 1 に入るよう -1)。
u = 1(既定)= 追加のビン化なし。
リスト [e1, e2, …, ek](昇順): 非周期的な明示ビン境界
各 e はその値以下を含む上限。k + 1 個のビンを生成(最終ビンは開区間):
値 ≤ e1 → bin 1
e1 < 値 ≤ e2 → bin 2
- …
値 > ek → bin k + 1
例(frequency): frequency_unit=[1, 3, 10] → 1回→bin 1, 2〜3回→bin 2, 4〜10回→bin 3,
11回以上→bin 4。
例(recency): recency_unit=[7, 30] → 0〜7日→bin 1, 8〜30日→bin 2, 31日以上→bin 3。
想定する使い分け(根拠)
recency_unit は整数が中心。曜日・月などの周期性を使うため(例: 7=週、30≈月)。
frequency_unit はリストが中心。接触回数は 1回 / 2〜3回 / 4〜10回 のように非周期的に
区切ることが多いため。
設計・相互作用メモ
frequency_unit は frequency_mode と直交。view freq でも day freq でも、得られた頻度値を
ビン化する。
recency_unit(整数・リスト)は recency_mode="view" 時は無視(recency はランク)。
- ビン化は
_recency.py ビルダー内の生値への純粋な後処理。groupby を増やさない。
スコープ外 / 未決事項
- リスト境界の正確な規約(上限含む方式 等)は design で確定。上記は提案仕様。
recency_mode="session" は将来・別扱い。
受け入れ条件
Overview
Two related additions on the frequency axis, plus a list-binning extension shared with the
recency axis:
frequency_mode— aggregate frequency at day granularity (distinct interaction days) inaddition to the current view granularity (interaction count). Frequency-axis counterpart of
recency_mode(v0.6.0); reuses the{day, view}vocabulary.frequency_unit— bin the frequency value, as an int (fixed-width / periodic bins, likerecency_unit) or a list (explicit, non-periodic bin edges).recency_unitlist support — extendrecency_unitto also accept a list of bin edges(currently int only).
Part 1 —
frequency_modeTerminology
frequency_mode="view"(default)frequency_mode="day"Definition
frequency_mode="view"(default):frequency = interaction count— current behavior.frequency_mode="day":frequency = number of distinct interaction days=nuniqueof the dayordinal (
_SEQUENCE_COL).Example
A user interacts with item A:
day freq caps many same-day interactions, bounding frequency by the number of days in the
observation window. Already demonstrated via manual preprocessing in
examples/tutorial_advanced_day_freq_{en,ja}.ipynb; this makes it a first-class parameter.Design notes
"view"to preserve current behavior (intentional default asymmetry vsrecency_mode="day": classic RF is time-based for recency, count-based for frequency).recency_modeand the high-resolution view key: day freq uses the day ordinal(
_SEQUENCE_COL), which always exists. No high-resolution key needed._recency.pybuilders: the frequency named-agg entry is(seq_col, "count")for view,(seq_col, "nunique")for day. No extra groupby.Part 2 —
frequency_unit/recency_unitbinningBoth
recency_unitandfrequency_unitaccept an int or a list:Int
u(≥ 1): fixed-width / periodic binsThe raw metric is divided into width-
ubins (1-indexed; smallest value → bin 1).(ref - last_view) // u + 1(current behavior).(f - 1) // u + 1(the-1makesf = 1fall in bin 1).u = 1(default) = no extra binning.List
[e1, e2, …, ek](ascending): explicit, non-periodic bin edgesInclusive upper bounds; produces
k + 1bins (the last is open-ended):value ≤ e1→ bin 1e1 < value ≤ e2→ bin 2value > ek→ bink + 1Example (frequency):
frequency_unit=[1, 3, 10]→1→bin 1,2–3→bin 2,4–10→bin 3,11+→bin 4.Example (recency):
recency_unit=[7, 30]→0–7 days→bin 1,8–30→bin 2,31+→bin 3.Intended usage (rationale)
recency_unitis typically an int, exploiting calendar periodicity (e.g.7= weekly,30≈ monthly).frequency_unitis typically a list, since interaction counts are usually groupednon-periodically (e.g.
1vs2–3vs4–10).Design / interaction notes
frequency_unitis orthogonal tofrequency_mode: it bins the resulting frequency valuewhether it is view freq or day freq.
recency_unit(int or list) is ignored whenrecency_mode="view"(recency is a rank)._recency.pybuilders; no extra groupby.Out of scope / open questions
is the proposed spec.
recency_mode="session"remains future and separate.Acceptance criteria
frequency_mode: str = "view"added; unknown values raiseValueErrorfrequency_mode="view"reproduces current results;frequency_mode="day"= distinctinteraction days (matches example)
frequency_unitadded (default1); accepts int (periodic) and list (edges)recency_unitextended to accept a list (int behavior unchanged;recency_unit=1identicalto current)
ValueError_recency.py(no extra groupby); worksacross
fit(),fit_rolling(),transform()frequency_mode/frequency_unit(and listrecency_unit) persisted tosave_zip()metadata and shown in
show()functional-design.md,glossary.md,product-requirements.md); alignglossary day freq wording to 接触日数 (currently "閲覧日数"); reference the existing
day-freq tutorials
概要
頻度(frequency) 軸に関する2つの追加と、recency 軸と共通のリストビン化拡張:
frequency_mode— 頻度を現状の view 粒度(接触回数)に加えて day 粒度(接触日数)でも集計する。v0.6.0 の
recency_modeの頻度軸版で、{day, view}語彙を踏襲。frequency_unit— 頻度の値をビン化する。整数(等幅・周期的ビン、recency_unitと同じ)または リスト(非周期的な明示ビン境界)。
recency_unitのリスト対応 —recency_unitもビン境界のリストを受け付けるよう拡張(現状は整数のみ)。
Part 1 —
frequency_mode用語整理
frequency_mode="view"(既定)frequency_mode="day"定義
frequency_mode="view"(既定):頻度 = 接触回数— 現状の挙動。frequency_mode="day":頻度 = 接触したユニーク日数= 日序数(_SEQUENCE_COL)のnunique。例
あるユーザーが商品 A に接触:
day freq は同日内の多数の接触を抑え、頻度の上限を観測期間の日数で抑える。既に
examples/tutorial_advanced_day_freq_{en,ja}.ipynbで手動前処理として実演済みで、本 Issue はこれを正式なパラメータにする。
設計メモ
"view"必須(現状挙動の保持)。recency_mode="day"との既定非対称は意図的(古典的 RF:recency は時間ベース・frequency は回数ベース)。
recency_mode・高解像度キーと直交: day freq は日序数(_SEQUENCE_COL)から計算でき、両 recencyモードで常に存在するため高解像度キーは不要。
_recency.pyのビルダーで frequency の named-agg を(seq_col, "count")(view)↔
(seq_col, "nunique")(day)と切り替えるだけ。groupby を増やさない。Part 2 —
frequency_unit/recency_unitのビン化recency_unit・frequency_unitはともに 整数 または リスト を受け付ける:整数
u(≥ 1): 等幅・周期的ビン生の指標を幅
uの等幅ビンに分割(1 起算、最小値 → bin 1)。(ref - last_view) // u + 1(現状の挙動)。(f - 1) // u + 1(f = 1が bin 1 に入るよう-1)。u = 1(既定)= 追加のビン化なし。リスト
[e1, e2, …, ek](昇順): 非周期的な明示ビン境界各 e はその値以下を含む上限。
k + 1個のビンを生成(最終ビンは開区間):値 ≤ e1→ bin 1e1 < 値 ≤ e2→ bin 2値 > ek→ bink + 1例(frequency):
frequency_unit=[1, 3, 10]→1回→bin 1,2〜3回→bin 2,4〜10回→bin 3,11回以上→bin 4。例(recency):
recency_unit=[7, 30]→0〜7日→bin 1,8〜30日→bin 2,31日以上→bin 3。想定する使い分け(根拠)
recency_unitは整数が中心。曜日・月などの周期性を使うため(例:7=週、30≈月)。frequency_unitはリストが中心。接触回数は1回/2〜3回/4〜10回のように非周期的に区切ることが多いため。
設計・相互作用メモ
frequency_unitはfrequency_modeと直交。view freq でも day freq でも、得られた頻度値をビン化する。
recency_unit(整数・リスト)はrecency_mode="view"時は無視(recency はランク)。_recency.pyビルダー内の生値への純粋な後処理。groupby を増やさない。スコープ外 / 未決事項
recency_mode="session"は将来・別扱い。受け入れ条件
frequency_mode: str = "view"を追加。未知値はValueErrorfrequency_mode="view"で現状結果と一致、frequency_mode="day"で接触ユニーク日数(例と一致)frequency_unitを追加(既定1)。整数(周期的)・リスト(境界)を受け付けるrecency_unitをリスト対応に拡張(整数の挙動は不変。recency_unit=1は現状と一致)ValueError_recency.pyの単一 groupby 後処理で実装(groupby を増やさない)。fit()/fit_rolling()/transform()で動作frequency_mode/frequency_unit(およびリストのrecency_unit)をsave_zip()metadata とshow()に反映functional-design.md/glossary.md/product-requirements.md)。glossary のday freq 表記を 接触日数 に揃える(現状「閲覧日数」)。既存 day-freq チュートリアルを参照