如何在不使用循环的情况下获取大于或小于 NumPy 数组中每个项目的项目索引?

How to get indexes of items greater or less than each item in a NumPy array without using a loop?

我正在从头开始编写决策树算法,现在我正在尝试将数据分成组,其中每个组包含的值大于或等于或小于包含值的 NumPy 数组中的每个值一个连续的 DataFrame 列,并获取这些拆分目标的平均值。 到目前为止我的代码:

for i in range(len(columns)):
    col = columns[i]
    # cont - list of continous columns in my DataFrame
    if col in cont:
        values  = xs[col].values
        targets = y.values
        for j in range(len(values)):
            value = values[j]
            greater_idx = np.where(values >= value)[0]
            less_idx    = np.where(values <  value)[0]
            targets_greater = targets[greater_idx].sum()
            targets_less    = targets[less_idx]   .sum()
        print(targets_greater/(j+1))
        print(targets_less   /(j+1))

xs DataFrame 的长度将近 400k,所以循环真的很慢,每次都会杀死我的 Jupyter Notebook 内核。我知道应该有办法完全摆脱那个循环,但我不确定该怎么做。

与其使用矢量化方式执行比较,算法还有很大的改进空间:

  1. 使用 np.argsort (sorted_idxs) 获取 xs[col].values 的排序索引。
  2. 使用 np.insert(np.cumsum(targets[sorted_idxs]), 0, 0)[:-1]xs[col].values 中的每个值得到一个 target_less 的向量。
  3. target_less[0] (0) 是 xs[col].values 中最低元素的 target_less 值 - 要“取消排序”target_less,您可以使用 unsort_idx = np.argsort(sorted_idxs)target_less[unsort_idx].

现在您拥有数组中所有值的所有 target_less 值(target_greater 当然可以通过 targets.sum() - target_less 轻松获得)。

编辑:

下面是符合建议的代码:

import numpy as np
import pandas as pd

xs = pd.DataFrame(np.random.random(10000))
y = pd.Series(np.random.randint(0, 2, size=10000))

sorted_idxs = np.argsort(xs[0].values)
sorted_values = xs[0].values[sorted_idxs]
sorted_targets = y.values[sorted_idxs]
sorted_targets_less = np.insert(np.cumsum(sorted_targets), 0, 0)[:-1]

unsorted_idxs = np.argsort(sorted_idxs)
targets_less = sorted_targets_less[unsorted_idxs]

for i, target_less_value in enumerate(targets_less):
    assert target_less_value == y.values[np.where(xs.values < xs.values[i])[0]].sum()

一个警告词:以上假定 xs.values 中有一组严格不同的值。如果你有重复的值,那么你需要调整做累加和的部分。