我在Jupyter中运行了此文件,并将exampledata.txt放置在与笔记本相同的目录中。
请注意第一行:
df = pd.Dataframe(datas, columns=['userid', 'recency', 'frequency', 'monetary'])
'userid'未在数据文件中定义时加载列。我删除了此列名。
解
import pandas as pddef pct_rank_qcut(series, n): edges = pd.Series([float(i) / n for i in range(n + 1)]) f = lambda x: (edges >= x).argmax() return series.rank(pct=1).apply(f)datas = pd.read_csv('./exampledata.txt', delimiter=';')df = pd.Dataframe(datas, columns=['recency', 'frequency', 'monetary'])df['recency'] = df['recency'].astype(float)df['frequency'] = df['frequency'].astype(float)df['monetary'] = df['monetary'].astype(float)df['recency'] = pct_rank_qcut(df.recency, 5)df['frequency'] = pct_rank_qcut(df.frequency, 5)df['monetary'] = pct_rank_qcut(df.monetary, 5)说明
您看到的问题是pd.qcut的结果,假设5个bin大小相等。在您提供的数据中,
'frequency'数字1超过28%。这打破了
qcut。
我提供了一个新功能
pct_rank_qcut来解决此问题,并将所有1推入第一个bin。
edges = pd.Series([float(i) / n for i in range(n + 1)])
这条线基于定义的bin的所需数量定义了一系列百分比边缘
n。在
n = 5边缘的情况下
[0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
f = lambda x: (edges >= x).argmax()
该行定义了辅助功能,该功能将应用于下一行中的另一个系列。
edges >=x将返回一个长度相等于
edges每个元素所在位置的序列,
True或者
False取决于是否
x小于或等于该边缘。在
x =0.14结果
(edges >= x)将为的情况下
[False, True, True, True, True,True]。通过这种情况,在这种情况下,
argmax()我已经确定了系列的第一个索引。
True``1
return series.rank(pct=1).apply(f)
该行接受输入
series并将其转换为百分等级。我可以将这些排名与创建的边缘进行比较,这就是为什么要使用的原因
apply(f)。返回的应该是一系列从1到n的箱号。这一系列的箱号与您尝试获得的相同:
pd.qcut(df['recency'].values, 5).pres + 1
结果是仓不再相等,仓1完全从仓2借用。但是必须做出一些选择。如果您不喜欢这种选择,请使用此概念来建立自己的排名。
示范
print df.head() recency frequency monetary0 3 5 51 2 5 52 2 5 53 1 5 54 2 5 5
更新资料
pd.Series.argmax()现在已弃用。只需切换
pd.Series.values.argmax()()至更新!
def pct_rank_qcut(series, n): edges = pd.Series([float(i) / n for i in range(n + 1)]) f = lambda x: (edges >= x).values.argmax() return series.rank(pct=1).apply(f)



