"""时点聚合和折外目标编码：python 03_features.py。"""
from collections import Counter

def history(events, user, t, window=30):
    visible = [e for e in events if e[0] == user and t-window <= e[1] < t and e[2] <= t]
    return len(visible), sum(e[3] for e in visible)

events = [("u1", 10, 10, 50), ("u1", 12, 21, 100), ("u1", 23, 23, 10)]
assert history(events, "u1", 20) == history(events[:1], "u1", 20) == (1, 50)
print("history at days 20 and 25:", history(events, "u1", 20), history(events, "u1", 25))

def encoder(items, alpha=4):
    prior = sum(label for _, label in items) / len(items)
    count = Counter(key for key, _ in items)
    positives = Counter()
    for key, label in items:
        positives[key] += label
    return lambda key: (positives[key] + alpha * prior) / (count[key] + alpha)

rows = [("app", 1), ("web", 0), ("unique_7", 1), ("app", 0), ("web", 1), ("new", 0)]
fold = [0, 1, 0, 0, 1, 1]
oof = [encoder([row for row, f in zip(rows, fold) if f != fold[i]])(key)
       for i, (key, _) in enumerate(rows)]
full = encoder(rows)
print("unique category: same-data encoding =", full("unique_7"), "; OOF =", oof[2])
assert oof[2] == encoder([row for row, f in zip(rows, fold) if f == 1])("unseen")
print("OOF:", [round(value, 3) for value in oof])

