从数据集中过滤非“群组”

Rei*_*rne 7 python statistics data-modeling pandas

我确信之前已经研究过这个主题,我不确定它叫什么或者我还应该研究什么技术,因此我为什么在这里。我主要在 Python 和 Pandas 中运行它,但它不仅限于这些语言/技术。

举个例子,让我们假设我有这个数据集:

| PID | A    | B    | C    |
| --- | ---- | ---- | ---- |
| 508 | 0.85 | 0.51 | 0.05 |
| 400 | 0.97 | 0.61 | 0.30 |
| 251 | 0.01 | 0.97 | 0.29 |
| 414 | 0.25 | 0.04 | 0.83 |
| 706 | 0.37 | 0.32 | 0.33 |
| 65  | 0.78 | 0.62 | 0.25 |
| 533 | 0.24 | 0.15 | 0.88 |
Run Code Online (Sandbox Code Playgroud)

PID 是该行的唯一 ID。A、B 和 C 是一些因素(针对此示例进行了标准化)。该数据集可以是历史上体育联盟的球员,可以是库存中的产品,也可以是选民数据。具体的上下文并不重要。

现在假设我有一些输入数据:

| A    | B    | C    |
| ---- | ---- | ---- |
| 0.81 | 0.75 | 0.17 |
Run Code Online (Sandbox Code Playgroud)

此输入与原始数据集(A、B、C)共享相同的因素。我想要做的是找到与我的输入数据(“同类群组”)相似的行。解决这个问题的最佳方法是什么?

我想到了聚类,使用kNN算法,但问题是没有设置群组数量。您可以有独特的输入并且很少/没有“群组”,或者您可以使用非常常见的输入并且有数百个“群组”。

我接下来尝试的解决方案是欧几里得距离。所以对于这个数据集和输入,我会做这样的事情:

my_cols = ['A', 'B', 'C']

inputdata = pd.Series([0.81, 0.75, 0.17], index=['A', 'B', 'C'])

# df = pandas data frame with above data

df['Dict'] = (df[my_cols] - inputdata).pow(2).sum(1).pow(0.5)
Run Code Online (Sandbox Code Playgroud)

这将在数​​据集上创建一个新列,例如:

| PID | A    | B    | C    | Dist |
| --- | ---- | ---- | ---- | ---- |
| 508 | 0.85 | 0.51 | 0.05 | 0.27 |
| 400 | 0.97 | 0.61 | 0.30 | 0.25 |
| 251 | 0.01 | 0.97 | 0.29 | 0.84 |
| 414 | 0.25 | 0.04 | 0.83 | 1.12 |
| 706 | 0.37 | 0.32 | 0.33 | 0.63 |
| 65  | 0.78 | 0.62 | 0.25 | 0.16 |
| 533 | 0.24 | 0.15 | 0.88 | 1.09 |
Run Code Online (Sandbox Code Playgroud)

然后,您可以“过滤”出低于某个阈值的那些行。

cohorts = df[df['Dist'] <= THRESHOLD]
Run Code Online (Sandbox Code Playgroud)

那么问题就变成了 (1) 您如何确定最佳阈值?(2) 如果我在数据集和 Euclid 计算中添加第 4 个因子(“D”),它似乎“破坏”了结果,因为从结果来看,队列不再具有直观意义。

所以我的问题是:过滤/选择“同类群组”(与输入行类似的那些行)的技术或更好的方法是什么?

谢谢

Erf*_*fan 2

这是我通过逻辑思维和一些基本统计数据自己想出的算法。它使用mean输入数据的值和平均值来根据使用查找最接近的匹配standard deviationpd.merge_asof

factors = ['A', 'B', 'C']
df = df.assign(avg=df[factors].mean(axis=1)).sort_values('avg')
input_data = input_data.assign(avg=input_data[factors].mean(axis=1)).sort_values('avg')

dfn = pd.merge_asof(
    df,
    input_data,
    on='avg',
    direction='nearest',
    tolerance=df['avg'].std()
)
Run Code Online (Sandbox Code Playgroud)
   PID   A_x   B_x   C_x       avg   A_y   B_y   C_y
0  706  0.37  0.32  0.33  0.340000   NaN   NaN   NaN
1  414  0.25  0.04  0.83  0.373333   NaN   NaN   NaN
2  251  0.01  0.97  0.29  0.423333   NaN   NaN   NaN
3  533  0.24  0.15  0.88  0.423333   NaN   NaN   NaN
4  508  0.85  0.51  0.05  0.470000   NaN   NaN   NaN
5   65  0.78  0.62  0.25  0.550000  0.81  0.75  0.17
6  400  0.97  0.61  0.30  0.626667  0.81  0.75  0.17
Run Code Online (Sandbox Code Playgroud)