相似度计算中的熊猫序数变量处理

时间:2015-04-24 11:00:00

标签: python pandas distance similarity categorical-data

我有一个Pandas版本0.15.2数据帧,如下所示,序号列rate,最初表示为字符串。我的最终目标是找到df中不同行的相似之处(实际上我有更多的行和更多的序数变量)。

目前,在执行我想要的排序时,我factorize()首先将rate转换为Categorical,然后对df进行排序,最后将因子分解为Bad得到最小的整数值,Good获得最高值。以这种方式,我创建factor_rate列,然后我可以将其用作维度(以及其他)来计算相似度/距离。这些在下面的代码中给出。

然而,我觉得这是一个内存效率低下且速度慢的黑客。什么是实现这一目标的最快和最节省内存的方法?

df = pd.DataFrame({'id' : range(1,9),
                   'rate' : ['bad', 'bad', 'neutral', 'good',
                                'neutral', 'good', 'bad', 'neutral'],
                   'amount' : np.random.randn(8)},  columns= ['id','rate','amount'])

df.rate = pd.Categorical(df.rate, categories=["bad","neutral","good"], ordered=True)

df = df.sort('rate', ascending=True)
df.loc[:,'factor_rate'] = pd.factorize(df.rate)[0]

注1 :此问题与我之前的one相关联。

注意2 :我知道pandas.factorize()有一个order参数,现在或很快就会被弃用,所以我不能直接使用它。

注释3 :我知道Gower指标,在相似度计算中,序数变量应该与纯数字变量区别对待,但这不是我的问题。

1 个答案:

答案 0 :(得分:1)

如果您关注或依赖于分类,则另一种方法是在列表和订单中定义您的类别,使用此方法创建一个dict以将订单映射到类别并将此dict传递给map

In [560]:

df = pd.DataFrame({'id' : range(1,9),
                   'rate' : ['bad', 'bad', 'neutral', 'good',
                                'neutral', 'good', 'bad', 'neutral'],
                   'amount' : np.random.randn(8)},  columns= ['id','rate','amount'])
cat_list = ["bad","neutral","good"]
cat_dict = dict(zip(cat_list, np.arange(len(cat_list))))

df['factor_rate'] = df['rate'].map(cat_dict)
df
Out[560]:
   id     rate    amount  factor_rate
0   1      bad -1.436574            0
1   2      bad  0.210717            0
2   3  neutral -0.896904            1
3   4     good -1.724393            2
4   5  neutral  1.792339            1
5   6     good -1.312713            2
6   7      bad  0.555877            0
7   8  neutral -0.681881            1

按新的'factor_rate'列进行排序会产生与当前解决方案相同的输出:

In [562]:

df.sort('factor_rate')
Out[562]:
   id     rate    amount  factor_rate
0   1      bad -1.436574            0
1   2      bad  0.210717            0
6   7      bad  0.555877            0
2   3  neutral -0.896904            1
4   5  neutral  1.792339            1
7   8  neutral -0.681881            1
3   4     good -1.724393            2
5   6     good -1.312713            2

修改

实际上,底层编码存储在Category dtype:

In [569]:

df = pd.DataFrame({'id' : range(1,9),
                   'rate' : ['bad', 'bad', 'neutral', 'good',
                                'neutral', 'good', 'bad', 'neutral'],
                   'amount' : np.random.randn(8)},  columns= ['id','rate','amount'])
​
df['rate'] = pd.Categorical(df.rate, categories=["bad","neutral","good"], ordered=True)
df['rate'].cat.codes
Out[569]:
0    0
1    0
2    1
3    2
4    1
5    2
6    0
7    1
dtype: int8

所以我的答案可能没有必要,目前docs的链接是空的。