【问题标题】:*Vectorized* way to find indices of minimums for each column (excluding all already found indices)*矢量化*方法来查找每列的最小值索引(不包括所有已找到的索引)
【发布时间】:2018-03-22 17:01:46
【问题描述】:

我有以下方形 DataFrame:

In [104]: d
Out[104]:
           a          b          c          d          e
a        inf   5.909091   8.636364   7.272727   4.454545
b   7.222222        inf   8.666667   7.666667   1.777778
c  15.833333  13.000000        inf   9.166667  14.666667
d   4.444444   3.833333   3.055556        inf   4.833333
e  24.500000   8.000000  44.000000  43.500000        inf

这是修改后的距离矩阵,表示对象 ['a','b','c','d','e'] 之间的成对距离,其中每一行除以一个系数(权重)并且所有对角线元素人为设置为np.inf

如何以高效矢量化)方式获得如下索引列表/向量:

d   # index of minimal element in the column `a`
a   # index of minimal element in the column `b` (excluding already found indices: [d]) 
b   # index of minimal element in the column `c` (excluding already found indices: [d,a]) 
c   # index of minimal element in the column `d` (excluding already found indices: [d,a,b]) 

即在第一列中我们找到了索引d,所以当我们在第二列中搜索最小值时,我们排除了索引为d(之前在第一列中找到)的行——这将是a

当我们在第三列中寻找最小值时,我们会排除具有先前找到的索引的行 (['d','a']) - 这将是 b

当我们在第四列中寻找最小值时,我们会排除具有先前找到的索引的行 (['d','a','b']) - 这将是 c

我不需要对角线 (inf) 元素,因此生成的列表/向量将包含 d.shape[0] - 1 元素。


即结果列表将如下所示:['d','a','b','c'] 或在 Numpy 解决方案的情况下,相应的数字索引:[3,0,1,2]

使用慢速for loop 解决方案不是问题,但我无法围绕矢量化(快速)解决方案...

【问题讨论】:

  • 你能解释一下excluding already found indices:的意思吗?
  • 预期输出的第三行有错字,我想应该是b(下一行实际上显示b作为已找到的索引)。我假设列e 的最小元素没有显示/需要,因为它可以通过排除来确定?无论如何,我不确定 can 是否是矢量化解决方案,与上一列的结果存在硬依赖...
  • @jdehesa,是的,坦克很多!我现在已经更正了...
  • @cᴏʟᴅsᴘᴇᴇᴅ,我已经用简短的解释更新了我的问题...
  • 根据您更新的解决方案,我是这样理解的:“当前步骤的结果取决于上一步的结果”。我想不出没有循环的方法:(

标签: python pandas numpy


【解决方案1】:

循环是我在这里看到的唯一解决方案。

但您可以使用numpy + numba 进行优化。

from numba import jit

@jit(nopython=True)
def get_min_lookback(A, res):
    for i in range(A.shape[1]):
        res[i] = np.argmin(A[:, i])
        A[res[i], :] = np.inf
    return res

arr = df.values

get_min_lookback(arr, np.zeros(arr.shape[1], dtype=int))

# array([3, 0, 1, 2, 0])

【讨论】:

    【解决方案2】:

    这是我的解决方案,我敢肯定这不是最好的:

    结果列表:

    res = []
    

    主函数,将在列中搜索最小值,排除先前找到的索引并将找到的索引添加到res

    def f(col):
        ret = col.loc[~col.index.isin(res)].idxmin()
        if ret not in res:
            res.append(ret)
    

    对每一列应用函数:

    _ = d.apply(f)
    

    结果:

    In [55]: res
    Out[55]: ['d', 'a', 'b', 'c', 'e']
    

    不包括最后一个元素:

    In [56]: res[:-1]
    Out[56]: ['d', 'a', 'b', 'c']
    

    【讨论】:

      猜你喜欢
      • 2018-01-29
      • 1970-01-01
      • 2019-01-21
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2013-06-12
      • 1970-01-01
      • 2016-09-06
      相关资源
      最近更新 更多