如何在不使用循环的情况下获取大于或小于 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 内核。我知道应该有办法完全摆脱那个循环,但我不确定该怎么做。
与其使用矢量化方式执行比较,算法还有很大的改进空间:
- 使用
np.argsort
(sorted_idxs
) 获取 xs[col].values
的排序索引。
- 使用
np.insert(np.cumsum(targets[sorted_idxs]), 0, 0)[:-1]
为 xs[col].values
中的每个值得到一个 target_less
的向量。
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 中有一组严格不同的值。如果你有重复的值,那么你需要调整做累加和的部分。
我正在从头开始编写决策树算法,现在我正在尝试将数据分成组,其中每个组包含的值大于或等于或小于包含值的 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 内核。我知道应该有办法完全摆脱那个循环,但我不确定该怎么做。
与其使用矢量化方式执行比较,算法还有很大的改进空间:
- 使用
np.argsort
(sorted_idxs
) 获取xs[col].values
的排序索引。 - 使用
np.insert(np.cumsum(targets[sorted_idxs]), 0, 0)[:-1]
为xs[col].values
中的每个值得到一个target_less
的向量。 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 中有一组严格不同的值。如果你有重复的值,那么你需要调整做累加和的部分。