我正在从头开始编写决策树算法,现在我正试图将数据分成组,其中每个组包含的值大于或等于或小于包含连续DataFrame列值的NumPy数组中的每个值,并获得这些分割目标的平均值。我的代码到目前为止:
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
值-到"unsort"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()
一个警告:上面假设在x .values中有一组严格不同的值。如果有重复的值,则需要调整进行累积和的部分。