使用表合并数据帧

时间:2016-07-11 11:13:16

标签: python pandas

我有一个相似矩阵(构建为数据帧):

mat = pd.DataFrame(index = df.a.values,columns = df.a.values)
mat[:] = [[1,0.2,0.3],[0.7,1,0.6],[0,0.4,1]]
    id1     id2     id3
id1 1.0     0.2     0.3
id2 0.7     1.0     0.6
id3 0.0     0.4     1.0

我想创建另一个包含相同索引但包含最近id的列的数据框:

    id      closest
0   id1     id3
1   id2     id1
2   id3     id2

我们的想法是在相似度矩阵中寻找第二个最高值的每一行(第一个在对角线上始终为1),并检索相应列的名称。

我知道我可以将对角线设置为零,然后使用类似的东西:

def closest(x):
    return np.where(x == x.max())

temp = mat.apply(lambda x: closest(x))
df['closest'] = df.index[[w[0][0] for w in temp.values]].tolist()

但我无法在不重新分配的情况下找到如何过滤对角线。

注意:矩阵中的值都在0到1之间,唯一的1在对角线上

2 个答案:

答案 0 :(得分:2)

减去单位矩阵,然后使用DataFrame.idxmax()查找每行中最大值的索引。

import numpy as np
import pandas as pd

index = ['id1', 'id2', 'id3']
mat = pd.DataFrame([[1, 0.2, 0.3],[0.7, 1, 0.6],[0, 0.4, 1]],
                   index=index, columns=index)

(mat - np.identity(3)).idxmax(axis=1)

输出:

id1    id3
id2    id1
id3    id2
dtype: object

答案 1 :(得分:1)

一种方法是通过减去相同顺序的单位矩阵来摆脱对角线1。如果你不想做任何重新分配或减去(我没有看到原因 - 可能是为了练习在Pandas中使用许多功能),我会建议这样的事情:

def closest(x):
  return mat.loc[x['id']].nlargest(2).values.tolist()[1]

def closest_label(x):
  return mat.loc[x['id']].nlargest(2).index[1]

df['closest'] = df.apply(closest, axis=1)
df['closest_label'] = df.apply(closest_label, axis=1)

输出:

    id  closest closest_label
0  id1      0.3           id3
1  id2      0.7           id1
2  id3      0.4           id2