- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有数据集:
recency;frequency;monetary
21;156;41879955
13;88;16850284
8;74;79150488
2;74;26733719
9;55;16162365
...;...;...
详细原始数据-> http://pastebin.com/beiEeS80然后我放入 DataFrame
,这是我的完整代码:
df = pd.DataFrame(datas, columns=['userid', 'recency', 'frequency', 'monetary'])
df['recency'] = df['recency'].astype(float)
df['frequency'] = df['frequency'].astype(float)
df['monetary'] = df['monetary'].astype(float)
df['recency'] = pd.qcut(df['recency'].values, 5).codes + 1
df['frequency'] = pd.qcut(df['frequency'].values, 5).codes + 1
df['monetary'] = pd.qcut(df['monetary'].values, 5).codes + 1
但是返回错误
df['frequency'] = pd.qcut(df['frequency'].values, 5).codes + 1
ValueError: Bin edges must be unique: array([ 1., 1., 2., 4., 9., 156.])
如何解决?
最佳答案
我在 Jupyter 中运行它并将 exampledata.txt 放在与笔记本相同的目录中。
请注意第一行:
df = pd.DataFrame(datas, columns=['userid', 'recency', 'frequency', 'monetary'])
加载未在数据文件中定义的列 'userid'
。我删除了这个列名。
import pandas as pd
def 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'
有超过 28% 的数字为 1。这破坏了 qcut
。
我提供了一个新函数 pct_rank_qcut
来解决这个问题并将所有 1 插入第一个 bin。
edges = pd.Series([float(i) / n for i in range(n + 1)])
此行根据 n
定义的所需 bin 数量定义了一系列百分位数边缘。在 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 的 bin 编号。这一系列的 bin 编号与您试图获得的相同:
pd.qcut(df['recency'].values, 5).codes + 1
这会导致 bin 不再相等并且 bin 1 完全从 bin 2 借用。但是必须做出一些选择。如果您不喜欢这个选择,请使用这个概念来建立您自己的排名。
print df.head()
recency frequency monetary
0 3 5 5
1 2 5 5
2 2 5 5
3 1 5 5
4 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)
关于python - 为什么使用 pandas qcut 返回 ValueError : Bin edges must be unique?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36880490/
假设我有一个数据框: import numpy as np import pandas as pd df = pd.DataFrame(np.random.normal(0,1,[100,50]))
我想将 pandas qcut 应用于滚动窗口。我不知道该怎么做...想法是在过去 20 天中,找到属于上四分位数的值,找到上四分位数中的值的平均值。并返回该滚动时间序列的平均值。 如果我有 s =
这是一个简单的数据样本系列: sample Out[2]: 0 0.047515 1 0.026392 2 0.024652 3 0.022854 4 0.020397
我创建了一个分类变量,我想为其他变量的特定值创建一个新类别 我有一个带有变量 Score 的数据框,其值介于 0-100 之间。我做了十分之一,但我想为特定值创建一个新类别 df['Score_pr'
考虑以下数据: s = pd.Series([1, 1, 1, 2]) pd.qcut(s, 2, labels=False) 我想要等概率组,即 [0, 0, 1, 1]。相反,qcut 可以引发异
在此处的 Pandas 笔记本上 http://nbviewer.ipython.org/urls/raw.github.com/carljv/Will_it_Python/master/ARM/ch
我有一个数据框,我可以从中选择一个列(系列),如下所示: df: value_rank 275488 90 275490 35 275491
Pandas docs关于 qcut 函数有这样的说法: Discretize variable into equal-sized buckets based on rank or based on
我使用 pandas.qcut 将数据分为 5 组,并希望根据 qcut 的最小和最大分数来标记每个组。 例如,我尝试使用数据框列中的“年龄”数据。 df['age group'] = pd.qcut
我正在慢慢地从 R 转向 python + pandas,我面临着一个我无法解决的问题...... 我需要离散化一列中的值,方法是将它们分配给 bin,并将具有这些 bin 名称的列添加到原始 Dat
假设我有一个列表: a = [3, 5, 1, 1, 3, 2, 4, 1, 6, 4, 8] 和一个子列表: b = [5, 2, 6, 8] 我想通过 pd.qcut(a,2) 获取 bin 并计
有没有一种方法可以构造 Pandas groupby 和 qcut 命令以返回具有嵌套图 block 的一列?具体来说,假设我有 2 组数据,我希望将 qcut 应用于每组,然后将输出返回到一列。这类
我的问题和上一个一样: Binning with zero values in pandas 但是,我仍然想在分位数中包含 0 值。有没有办法做到这一点?换句话说,如果我有 600 个值,其中 50%
有两个 ndarray: import pandas as pd import numpy as np a = np.arange(0,100, 10) b = np.random.random_in
我对 groupby 结果应用 qcut,以下是我的问题的简化版本: a = pd.DataFrame({'A':[1,1,1,1,2,2,2,2], 'B': [
我正在做 Recency-Frequency-Monetary 分析,虽然我有一个在 Python 中工作的模型,但由于生产代码主要是 PHP(Oracle 12c fwiw 或者也可以在 postg
我在名为example 的对象的列中有很多分数。我想将这些分数分成十分位数,并为每一行分配相应的十分位数间隔。我尝试了以下方法: import random import pandas as pd r
更新:从版本 0.20.0 开始,pandas cut/qcut 确实可以处理日期字段。参见 What's New了解更多。 pd.cut and pd.qcut now support dateti
我正在使用 pandas qcut 将一些数据分成 20 个 bin,作为数据准备的一部分,用于训练二进制分类模型,如下所示: data['VAR_BIN'] = pd.qcut(cc_data[va
我有一个包含 499 条记录的埃博拉数据集。我试图根据概率(概率变量)找到每个五分位数中的观察次数。观察次数应分为 0-20%、20-40% 等类别。我认为这样做的代码是, test = pd.qcu
我是一名优秀的程序员,十分优秀!